flash - Function.apply 不使用 thisArg 参数

标签 flash apache-flex actionscript-3 functional-programming

我正在编写一些 Actionscript3 代码,试图将方法应用于在运行时确定的对象。 Function.apply 的 AS3 文档和 Function.call两者都表明这些函数的第一个参数是执行函数时将用作“this”值的对象。

但是,我发现在所有情况下,当正在执行的函数是一个方法时,应用/调用的第一个参数都没有使用,并且“this”总是指该方法绑定(bind)到的原始对象。这是一些示例代码及其输出:

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”的内联匿名函数,这表明当正在应用/调用的函数不是绑定(bind)方法时会发生正确的行为。

当我尝试在方法上使用它时,我使用的应用/调用不正确吗? AS3 文档专门为此案例提供了代码,但是:
myObject.myMethod.call(myOtherObject, 1, 2, 3);

如果这确实被破坏了,除了将目标方法变成函数之外是否还有其他解决方法(在我看来,这会很丑陋)?

最佳答案

它不是“错误”,而是 call 的文档和 apply非常具有误导性,并且根本无法很好地解释正在发生的事情。所以这里是对正在发生的事情的解释。
Methods不同于 Functions在 ActionScript 中。 Methods被定义为类定义的一部分,并且方法总是绑定(bind)到该实例。参见 this link 的方法二.从那里引用:

Methods are functions that are part of a class definition. Once an instance of the class is created, a method is bound to that instance. Unlike a function declared outside a class, a method cannot be used apart from the instance to which it is attached.



因此,当您制作 new MyObj 的实例,它的所有方法都绑定(bind)到该实例。这就是为什么当您尝试使用 callapply ,您没有看到 this被覆盖。请参阅有关 Bound Methods 的部分详情。

见,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!

对比:
method = a.boundWork;
method() // a. TADA MAGIC!

请注意 boundWork无论您为 this 传递什么,都将始终在它所属的实例的上下文中执行与 callapply .在 ActionScript 中,这种行为正是类方法绑定(bind)到它们的实例的原因。所以无论它们在哪里使用,它们仍然指向它们来自的实例(这使得 actionscript 事件模型更加“理智”)。一旦你理解了这一点,那么解决方法应该变得显而易见。

对于您想要做一些魔术的地方,请避免使用基于 ActionScript 3 的硬绑定(bind)方法,而使用原型(prototype)函数。

例如,考虑以下 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将始终绑定(bind)到为其创建的实例。 pSayName是可用于 MyObj 的实例的函数但不绑定(bind)到它的特定实例。
call 的文档和 apply在技​​术上是正确的,只要你在谈论原型(prototype) functions而不是类methods ,我认为它根本没有提到。

关于flash - Function.apply 不使用 thisArg 参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7238962/

相关文章:

actionscript-3 - Flash Builder Rss feed 可以工作,但必须将每篇文章链接到其原始网页。如何?

actionscript-3 - Adobe Air mobile - 使用 SkinClass 允许滚动时,softKeyboardType 不起作用?

actionscript-3 - 如何在 Flex 中使用外部 ActionScript 文件

actionscript-3 - AS3 中的 PBKDF2WithHmacSHA1

javascript - 如果未配置闪光灯,那么在自动捕获图像时应该出现一些错误消息,我该怎么办

flash - 如何使用 StageScaleMode.SHOW_ALL 获取舞台尺寸?

java - FLEX java.home 路径反斜杠

apache-flex - 在 Adob​​e Flex 中获取用户的语言环境

Python:如何在 Firefox 中自动化 'Allow' flash 播放器内容?

flash - 谷歌是否计算来自 Flash 的反向链接?