var foo = {
bar: function() { return this.baz; },
baz: 1
};
(function(){
return typeof arguments[0]();
})(foo.bar);
为什么此代码会返回undefined
?
我认为arguments[0]
会保留foo.bar
,这是一个函数。当通过arguments[0]()
调用时,它应该返回函数求值的结果,在这种情况下1
。因此,typeof arguments[0]()
应返回“数字”(如typeof 1
)。相反,它返回undefined
。为什么呢?
答案 0 :(得分:8)
要理解为什么this
不是对函数所在对象的引用,您必须了解JavaScript没有类。它有功能。
在JavaScript中,函数永远不会严格“绑定”到对象,就像它们在Java,C#等类别中一样。 javascript函数只是另一种类型,如string
和number
,这意味着您可以像其他任何类型一样在变量中传递函数。在您的示例中,foo.bar
中包含的函数根本不知道foo
。这只是一个功能,关注自己的事业。
那么this
关键字的作用是什么?它指向执行上下文。在您的示例中,您从全局范围(即foo.bar
)调用window
内的函数,这就是它所指向的内容。您可以使用apply()
在正确的范围内调用该函数,但为此您需要访问该范围(在本例中为foo
对象)。如果没有对象,这就会消除传递函数的任何安全优势。
为了“解决”这个“问题”,ECMAScript 5(未来版本的JavaScript)引入了 bind()
。这个方便的函数允许您在将函数传递给另一个函数之前将函数绑定到某个执行范围,如下所示:
var foo = {
bar: function() { return this.baz; },
baz: 1
};
var callback = foo.bar.bind(foo);
(function(){
return typeof arguments[0]();
}(callback));
答案 1 :(得分:5)
代码无效,因为在匿名函数内部,当在另一个上下文中使用时,您将丢失对foo对象的this.baz
的引用
您可以使用apply()
方法重新定义上下文,如此
var foo = {
bar: function() { return this.baz; },
baz: 1
};
(function(){
return arguments[0].apply(foo);
})(foo.bar);
并且这正确返回1
因为apply()方法将执行上下文更改为作为参数传递的对象
typeof arguments[0].apply(foo);
按预期返回number
答案 2 :(得分:1)
你可以通过this
声明来反对foo。
你应该写一个像下面这样的包装器,如果我们想要在foo中有很多功能的时候想改变foo的名字,那将非常有帮助
var foo = {
bar: function() { return this.baz; },
baz: 1
};
(function(a){
for( var i in a){
if( typeof a[i] === "function" ){
a[i] = (function(f){
return function(){
return f.apply(a,arguments);
}
})(a[i])
}
}
})(foo);
(function(){
return typeof arguments[0]();
})(foo.bar);
答案 3 :(得分:-2)
这指的是条形函数本身。
var foo = {
bar: function() {return foo.baz; },
baz:1
};
(function(){
return typeof arguments[0]();
})(foo.bar);