flash – Function.apply不使用thisArg参数
我正在编写一些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); } } 输出: A B A A 对上述代码的一个小修改,以创建一个引用’this’的内联匿名函数,表明当被应用/调用的函数不是绑定方法时,会发生正确的行为. 当我尝试在方法上使用它时,我是否使用了apply / call错误? AS3文档专门为此案例提供了代码,但是: myObject.myMethod.call(myOtherObject,1,2,3); 如果这确实被打破了,除了将目标方法变成函数之外还有其他解决方法(在我看来这会非常难看)吗? 解决方法
它不是一个“bug”,但是调用和应用的文档非常具有误导性,并且在解释最新情况时并没有做得很好.所以这里是对正在发生的事情的解释.
方法与ActionScript中的函数不同.方法被定义为类定义的一部分,方法总是绑定到该实例.参见this link的方法.从那里引用:
因此,当您创建MyObj的新实例时,其所有方法都绑定到该实例.这就是为什么当你尝试使用call或apply时,你没有看到这被覆盖.有关详细信息,请参阅Bound Methods部分. 有关traits对象的解释,请参阅this document,其中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; }; 然后: 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 甚至更有趣: var method = a.unboundWork; method() // undefined. ACK! VS: method = a.boundWork; method() // a. TADA MAGIC! 请注意,无论您使用call或apply传入什么内容,boundWork都将始终在其所属实例的上下文中执行.在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); }; } 注意sayName和pSayName之间的声明差异. sayName将始终绑定到为其创建的实例. pSayName是一个可用于MyObj实例的函数,但未绑定到它的特定实例. 调用和应用的文档在技术上是正确的,只要你谈论的是原型函数而不是类方法,我认为它根本没有提及. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |