javascript这个封闭的外部函数有一个绑定'这个'

时间:2017-06-15 18:40:05

标签: javascript ecmascript-6 ecmascript-5

我无法理解这个问题。 我知道范围链,javascript中的回调,回调中 this 的值,因此箭头函数。

在javascript中,闭包可以通过作用域链访问封闭函数的变量。那么为什么关闭不能访问'这个'通过Function.prototype.bind绑定到闭包的父函数?变量'这个'不是范围链的一部分?

在chrome控制台中运行以下代码:

a = 4;
b = 6;
function outer(){
    function inner(){
        console.log(`this.a is ${this.a} and this.b is ${this.b}`);
    }
    inner();
}
outer.bind({a:1,b:3})()

并且控制台退回:

this.a is 4 and this.b is 6

3 个答案:

答案 0 :(得分:3)

这和闭包是JS中的两种不同机制,不应该混合使用。 这在外部函数中与内部函数完全分离。

在你的例子中,你期望内部函数具有来自外部函数的词法范围,而这不是它的工作方式。如果您使用箭头功能,它就像那样工作,因为这将是词法,并将从外部函数指向这个。 如果你将内部函数更改为箭头函数,你可以观察到这个行为// this.a是1而this.b是3

const inner =()=> {     的console.log(this.a is ${this.a} and this.b is ${this.b}); };

如果你想了解这是怎么表现我强烈推荐Kyle Simpson的书,它在github this & object prototypes

上免费

从书中。

要理解这种绑定,我们必须了解call-site:调用函数的代码中的位置(而不是声明它的位置)。我们必须检查呼叫网站以回答这个问题:这是什么引用?

所以你可以看到内部函数的位置与这将绑定的内容无关。 rules that defines how this will be bound

阅读上面的链接后,你应该对JS有更多的了解。

答案 1 :(得分:0)

  

变量'这个'不是范围链的一部分?

是的,确切地说。 this不是变量,而是特殊关键字。它会在每个函数调用中设置,在您的情况inner()中。 this范围内outer的内容并不重要。

但是有一个例外,其中函数可以选择退出此行为:箭头函数。他们确实在词汇上查找this,并忽略来自呼叫的值:

function outer(){
    const inner = () => {
        console.log(`this.a is ${this.a} and this.b is ${this.b}`);
    }
    inner();
}
outer.call({a:1,b:3})

答案 2 :(得分:0)

正如评论中所提到的,这是contextual reference,它可以根据您调用函数的方式进行更改(或者如果我们考虑箭头函数,则可以更改它)。查看代码的修改版本,其中显示了此上下文行为:

var a = 4;
var b = 6;
function outer(){
    document.write(`<p>[outer] this.a is ${this.a} and this.b is ${this.b}</p>`);

    function inner(msg){
      document.write(`<p>[${msg}] this.a is ${this.a} and this.b is ${this.b}</p>`);
    }
    inner('inner');
    this.inner = inner;
    this.inner('this.inner');
}
outer.bind({a:1,b:3})();

将输出:

[outer] this.a is 1 and this.b is 3

[inner] this.a is 4 and this.b is 6

[this.inner] this.a is 1 and this.b is 3

工作演示here