问题描述
我正在编写一些 Actionscript3 代码,尝试将方法应用于在运行时确定的对象.Function.apply 和 的 AS3 文档href="http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/Function.html#call%28%29">Function.call 都表示这些函数的第一个参数是在执行函数时将用作this"值的对象.
但是,我发现在所有情况下,当执行的函数是方法时,不使用 apply/call 的第一个参数,并且this"始终指的是绑定该方法的原始对象.下面是一些示例代码及其输出:
包{导入 flash.display.Sprite;公共类 FunctionApplyTest 扩展了 Sprite{公共函数 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);}}}内部类 MyObj{私有变量_name:字符串;公共函数 MyObj(name:String){_name = 名称;}公共函数 sayName():void{跟踪(_名称);}}
输出:
A乙一种一种
对上述代码稍作修改以创建一个引用this"的内联匿名函数,这表明当应用/调用的函数不是绑定方法时会发生正确的行为.
当我尝试在方法上使用 apply/call 时,我是否使用了不正确的应用/调用?但是,AS3 文档专门为此案例提供了代码:
myObject.myMethod.call(myOtherObject, 1, 2, 3);
如果这确实坏了,除了将目标方法变成函数(在我看来这会很丑陋)之外,还有其他解决方法吗?
它不是错误",但是 call
和 apply
的文档非常具有误导性,并且没有根本无法解释正在发生的事情.所以这里是对正在发生的事情的解释.
Methods
与 ActionScript 中的 Functions
不同.Methods
被定义为类定义的一部分,并且方法总是绑定到该实例.请参阅此链接的方法第二部分.从那里引用:
方法是作为类定义一部分的函数.一旦创建了类的实例,就会将一个方法绑定到该实例.与在类外声明的函数不同,方法不能与它所附加的实例分开使用.
因此,当您创建 请参阅本文档,了解特征对象,可能是因为动作脚本用于解析方法并用于幕后的性能原因.那个或类方法只是以下 ECMAScript 模式的语法糖: 那么: 甚至更有趣: 对比: 请注意, 对于您想要施展魔法的地方,请避免使用基于 ActionScript 3 的硬绑定方法,而使用原型函数. 例如,考虑以下 ActionScript 代码: 注意 I'm writing some Actionscript3 code that attempts to apply a method to an object that is determined at runtime. The AS3 documentation for Function.apply and Function.call both indicate that the first argument to those functions is the object which will be used as the 'this' value when the function is executed. However, I have found that in all cases when the function being executed is a method, the first parameter to apply/call is not used, and 'this' always refers to the original object to which that method was bound. Here is some example code and its output: Output: A minor modification to the above code to create an in-line anonymous function which refers to 'this' shows that the correct behavior occurs when the function being applied/called is not a bound method. Am I using apply/call incorrect when I attempt to use it on a method? The AS3 documentation specifically provides code for this case, however: If this is indeed broken, is there any work-around besides making the target methods into functions (which would be quite ugly, in my opinion)? Its not a "bug", but the documentation for So when you make a See, this document for an explanation of the traits object, which actionscript uses to resolve methods and used for performance reasons behind the scenes is probably to blame. That or class methods are just syntactic sugar for the following ECMAScript pattern: Then: or even more interesting: Vs: Notice that For places where you want to do some magic, avoid the ActionScript 3 based hard-bound methods in favor of prototype functions. For example, consider the following ActionScript code: Notice the declaration difference between The documentation for 这篇关于Function.apply 不使用 thisArg 参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!MyObj
的 new
实例时,其所有方法都绑定到该实例.这就是为什么当您尝试使用 call
或 apply
时,您不会看到 this
被覆盖.有关详细信息,请参阅fbf351e63e3d1020a9b>fa9b7b部分.var TestClass = function(data) {var self = this;this.data = 数据;this.boundWork = function() {返回 self.constructor.prototype.unboundWork.apply(self, arguments);};};TestClass.prototype.unboundWork = function() {返回 this.data;};
var a = new TestClass("a");var b = new TestClass("b");警报(a.boundWork());//一种警报(b.boundWork());//乙警报(a.unboundWork());//一种警报(b.unboundWork());//乙警报(a.boundWork.call(b));//一种警报(a.boundWork.call(未定义));//一种警报(a.unboundWork.call(b));//乙
var method = a.unboundWork;method()//未定义.确认!
method = a.boundWork;方法()//a.多田魔术!
boundWork
将始终在其所属实例的上下文中执行,无论您使用 call
为 this
传入什么> 或 申请
.在 ActionScript 中,这种行为正是类方法绑定到它们的实例的原因.因此,无论在哪里使用它们,它们仍然指向它们来自的实例(这使得 actionscript 事件模型更加理智").一旦你理解了这一点,那么解决方法就很明显了.包{导入 flash.display.Sprite;公共类 FunctionApplyTest 扩展了 Sprite{公共函数 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);//一种objA.pSayName.call(objB)//b <---}}}内部动态类 MyObj{私有变量_name:字符串;公共函数 MyObj(name:String){_name = 名称;}公共函数 sayName():void{跟踪(_名称);}原型.pSayName = function():void {跟踪(this._name);};}
sayName
和pSayName
之间的声明差异.sayName
将始终绑定到为其创建的实例.pSayName
是一个可用于 MyObj
实例但不绑定到它的特定实例的函数.call
和 apply
的文档在技术上是正确的,只要您谈论的是原型 functions
而不是 class methods
,我认为它根本没有提到.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
myObject.myMethod.call(myOtherObject, 1, 2, 3);
call
and apply
is very misleading and doesn't do a good job at all of explaining whats going on. So here is an explaination of what is happening.Methods
are different from Functions
in ActionScript. Methods
are defined as a part of a class defintion, and methods are always bound to that instance. See the Methods second of this link. To quote from there:new
instance of MyObj
, all of its methods are bound to that instance. Which is why when you try to use call
or apply
, you aren't seeing this
getting overridden. See the section on Bound Methods for details.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
will always get executed in the context of the instance it belongs to, no matter what you pass in for this
with call
or apply
. Which, in ActionScript, this behavior is exactly why class methods are bound to their instance. So no matter where they are used, they still point at the instance they came from (which makes the actionscript event model a little more "sane"). Once you understand this, then a work-around should become obvious.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
and pSayName
. sayName
will always be bound to the instance it was created for. pSayName
is a function that is available to instances of MyObj
but is not bound to a particular instance of it.call
and apply
are technically correct, as long as you are talking about prototypical functions
and not class methods
, which I don't think it mentions at all.