绑定范围 javascript

Bind scoping javascript

我正在尝试确定使用绑定的范围。我对 boundF1 的输出感到困惑。这是怎么回事?

// console.log(x) ReferenceError: x is not defined

// setting this.x - this here is global or window
this.x = 5;
console.log(x) // 5

function f1() {
  console.log(x); // 5
  console.log(this.x); // 5
}

// Lexically bound this to window 
f2 = () => {
  console.log(x); // 5
  console.log(this.x); // 5
}

f1()
f2()

boundF1 = f1.bind({x:1});
boundF2 = f2.bind({x:1});


boundF1() // 5 1 Why is this not 1, 1. How is x resolved here? Does it check local vars, then global vars. Would it ever use this? What is the scoping rule?

boundF2() // 5 5

原因 x 将始终在范围 中查找变量 。它与 this上下文)无关。当您调用 .bind 时,您只在函数内部设置 this 的值。

在f2中,因为是不可绑定的箭头函数,所以xthis.x都是指window.x.

在 f1 中,x 将首先尝试查找任何局部范围的变量 x,如果找不到,将在全局范围内搜索 x。但是因为它是绑定的,所以 this 不再指的是 window 而是指你绑定它的对象,所以 this.x 是你绑定它的对象的 x 值。

当您引用独立变量时,如 console.log(x),解释器将尝试在外部作用域的某处查找具有相同名称的独立变量。在这里,外部作用域最终到达全局作用域,因此 console.log(x) 解析为 console.log(window.x).

this 的属性不会 添加到函数的变量环境中;要引用 this 的属性,您必须明确地这样做,例如:

console.log(this.x);

并不是说您应该永远使用它,但是有 with,它可以让您引用对象的属性,就好像它们是独立变量一样(这听起来像您 的想法 会自动发生),但强烈不推荐(并且在严格模式下禁止)。

this.x = 5;

function f1() {
  with (this) {
    console.log(x); // 5
    console.log(this.x); // 5
  }
}

boundF1 = f1.bind({x:1});


boundF1()

在第一个打印语句中的函数 f1() 中,您正在打印 x 而不是 this.x,因此当您将它与对象 {x:1} 绑定时, Function.prototype.bind() 您正在将 this 作为 {x:1} 对象传递。 但是在函数中,您正在从全局范围而不是从您绑定到的 this 上下文中读取 x 的值。

所以当你执行函数 f1 并打印 x 时,它首先在本地范围内寻找 x,因为它没有找到任何它会在在这种情况下是全局范围的父范围。

如果没有在全局范围内声明 x 你会得到一个 ReferenceError:

function f1() {
  console.log(this.x); // 1
  console.log(x); // ReferenceError as x is not declared in any scope
}
f1.bind({x:1})();

作用域规则在MDN docs:

中解释

Scopes can also be layered in a hierarchy, so that child scopes have access to parent scopes, but not vice versa.