Cha*_*lis 9 apache-flex flash functional-programming actionscript-3
我正在编写一些Actionscript3代码,试图将方法应用于在运行时确定的对象.Function.apply和Function.call的AS3文档都指出这些函数的第一个参数是在执行函数时将用作'this'值的对象.
但是,我发现在所有情况下,当正在执行的函数是一个方法时,不使用apply/call的第一个参数,'this'总是引用该方法绑定的原始对象.这是一些示例代码及其输出:
package
{
import flash.display.Sprite;
public class FunctionApplyTest extends Sprite
{
public function FunctionApplyTest()
{
var objA:MyObj = new MyObj("A");
var objB:MyObj = new MyObj("B");
objA.sayName();
objB.sayName();
objA.sayName.apply(objB, []);
objA.sayName.call(objB);
}
}
}
internal class MyObj
{
private var _name:String;
public function MyObj(name:String)
{
_name = name;
}
public function sayName():void
{
trace(_name);
}
}
Run Code Online (Sandbox Code Playgroud)
输出:
A
B
A
A
Run Code Online (Sandbox Code Playgroud)
对上述代码的一个小修改,以创建一个引用'this'的内联匿名函数,表明当被应用/调用的函数不是绑定方法时,会发生正确的行为.
当我尝试在方法上使用时,我是否使用了apply/call错误?AS3文档专门为此案例提供了代码,但是:
myObject.myMethod.call(myOtherObject, 1, 2, 3);
Run Code Online (Sandbox Code Playgroud)
如果这确实被打破了,除了将目标方法变成函数之外还有其他解决方法(在我看来这会非常难看)吗?
J. *_*mes 17
它不是一个"错误",但是文档call
和apply
非常误导,并没有很好地解释发生了什么.所以这里是对正在发生的事情的解释.
Methods
与Functions
ActionScript 不同.Methods
被定义为类定义的一部分,方法总是绑定到该实例.请参阅此链接的方法第二部分.从那里引用:
方法是属于类定义的函数.创建类的实例后,方法将绑定到该实例.与在类外声明的函数不同,方法不能与它所附加的实例分开使用.
因此,当您创建new
实例时MyObj
,其所有方法都绑定到该实例.这就是为什么当你尝试使用call
或者apply
,你没有看到this
被覆盖的原因.有关详细信息,请参阅绑定方法部分.
请参阅此文档以获取traits对象的解释,其中actionscript用于解析方法并在幕后使用性能原因可能是罪魁祸首.那个或类方法只是以下ECMAScript模式的语法糖:
var TestClass = function(data) {
var self = this;
this.data = data;
this.boundWork = function() {
return self.constructor.prototype.unboundWork.apply(self, arguments);
};
};
TestClass.prototype.unboundWork = function() {
return this.data;
};
Run Code Online (Sandbox Code Playgroud)
然后:
var a = new TestClass("a");
var b = new TestClass("b");
alert(a.boundWork()); // a
alert(b.boundWork()); // b
alert(a.unboundWork()); // a
alert(b.unboundWork()); // b
alert(a.boundWork.call(b)); // a
alert(a.boundWork.call(undefined)); // a
alert(a.unboundWork.call(b)); // b
Run Code Online (Sandbox Code Playgroud)
甚至更有趣:
var method = a.unboundWork;
method() // undefined. ACK!
Run Code Online (Sandbox Code Playgroud)
VS:
method = a.boundWork;
method() // a. TADA MAGIC!
Run Code Online (Sandbox Code Playgroud)
请注意,boundWork
无论您this
使用call
或传入的是什么,它总是会在它所属的实例的上下文中执行apply
.在ActionScript中,这种行为正是将类方法绑定到其实例的原因.因此,无论它们在何处使用,它们仍然指向它们来自的实例(这使得actionscript事件模型更加"理智").一旦你理解了这一点,那么解决方法应该变得明显.
对于想要做一些魔术的地方,请避免使用基于ActionScript 3的硬绑定方法来支持原型函数.
例如,请考虑以下ActionScript代码:
package
{
import flash.display.Sprite;
public class FunctionApplyTest extends Sprite
{
public function FunctionApplyTest()
{
var objA:MyObj = new MyObj("A");
var objB:MyObj = new MyObj("B");
objA.sayName();
objB.sayName();
objA.sayName.apply(objB, []); // a
objA.sayName.call(objB); // a
objA.pSayName.call(objB) // b <---
}
}
}
internal dynamic class MyObj
{
private var _name:String;
public function MyObj(name:String)
{
_name = name;
}
public function sayName():void
{
trace(_name);
}
prototype.pSayName = function():void {
trace(this._name);
};
}
Run Code Online (Sandbox Code Playgroud)
注意sayName
和之间的声明差异pSayName
.sayName
将始终绑定到为其创建的实例.pSayName
是一个可用于实例的函数,MyObj
但不绑定到它的特定实例.
只要你谈论的是原型而不是阶级的文档,call
并且apply
在技术上是正确的,我认为它根本没有提及.functions
methods