不幸的是.bind
在创建更复杂的闭包时给了我一个悲伤。
我很感兴趣。为什么.bind在嵌套函数后似乎有不同的工作方式。
例如:
function t(){
t = t.bind({}); //correctly assigns *this* to t
function nested_t(){
nested_t = nested_t.bind({}); // fails to assign *this* to nested_t
return nested_t;
}
return nested_t();
}
//CASE ONE
alert(t());
// alerts the whole function t instead of nested_t
//CASE TWO
aleft(t.call(t));
// alerts the global object (window)
在这两种情况下,我都期待这样的行为:
function t(){
var nested_t = function nested_t(){
return this;
};
return nested_t.call(nested_t);
}
alert(t.call(t));
如果有人能够在第一个(和/或)第二个案例中解释.bind
的行为,那将非常感谢!
答案 0 :(得分:3)
所以,我不是完全重现你的问题(这两种情况都返回全局对象),但我会尝试解释我看到的代码。
function t(){
t = t.bind({}); //correctly assigns *this* to t
function nested_t(){
nested_t = nested_t.bind({}); // fails to assign *this* to nested_t
return this;
}
return nested_t();
}
//CASE ONE
alert(t());
让我们一步一步来。
首先,定义函数t()
。然后,在通话时,它会被干净的上下文覆盖。但是,我没有看到任何使用这种情况。
现在,定义了嵌套函数(nested_t
)。 通话后,会被干净的上下文覆盖。然后它会在调用时返回的上下文。
返回t()
。然后,您返回nested_t()
的结果,不 nested_t
本身。在原始函数调用中,仍然使用全局上下文调用nested_t
。
因此,当您运行t()
时,它将返回全局对象。
答案 1 :(得分:2)
目前还不清楚,您的代码正在尝试做什么。您可以找到.bind()
here的文档。看起来你可能在某种程度上误解了this
是什么以及如何使用它。无论如何,运行代码时会发生什么:
t
函数。t
函数。
t
将替换为新值(绑定到特定上下文的原始t
- 匿名空对象),不会以任何方式影响当前调用。此外,在覆盖全局t
时,本地t
表现为只读。您可以尝试使用以下代码进行检查:(function foo () { return (function bar () { bar = window.bar = 'baz'; return bar; })(); })()
并将返回值与window.bar
进行比较。nested_t
也会发生同样的事情。nested_t
来电的结果。 nested_t
返回调用它的上下文,即window
,因为没有指定上下文。具体来说,它没有使用空对象上下文调用,因为.bind()
内部不会影响调用本身。t
作为上下文调用。由于t
在其代码中的任何位置都没有使用其上下文(this
),因此没有任何改变。基本上,你混淆了两件事 - 函数实例和函数调用上下文。函数是JavaScript中的“一等公民” - 它是一个对象,您可以为其属性赋值。
function foo () {
foo.property = 'value';
}
foo(); // foo.property is assigned a value
这与函数调用上下文无关。当您调用函数时,上下文被分配给该调用,可以使用this
(函数体内)访问
function foo () {
this.property = 'value';
}
var object = {};
foo.call(object); // object.property is assigned a value
当您使用.bind()
时,您只需使用相同的代码创建一个新函数,该函数将锁定到特定的上下文。
function foo () {
this.property = 'value';
}
var fixedContext = {},
object = {};
bar = foo.bind(fixedContext);
foo.call(object); // fixedContext.property is set instead of object.property
但在这种情况下,还有函数实例foo
和bar
,它们也可以被赋予属性,并且与这些函数的调用的上下文无关。
答案 2 :(得分:1)
让我们看一下bind
的工作原理。首先,一级嵌套:
var foo = function() { return this.x; };
alert(foo()); // undefined
alert(foo.bind({x: 42})()); // 42
现在我们可以添加下一级嵌套:
var bar = function() { return foo.bind(this)(); };
alert(bar()); // undefined
alert(bar.bind({x: 42})());
我们将this
上下文传递给foo
- 猜猜是什么? - bind
。 bind
在范围之间的工作方式没有什么不同。唯一的区别是我们已将this
绑定在bar
内,因此bar
的正文可以在this
内重新绑定foo
。
正如一些评论者所指出的那样,覆盖自身的功能是一种巨大的代码味道。没有理由这样做;当你打电话给你时,你可以bind
上下文。
我非常强烈建议您阅读the documentation on bind
,然后尝试理解,以便从头开始编写基本版Function.prototype.bind
。