绑定范围 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中,因为是不可绑定的箭头函数,所以x
和this.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.
我正在尝试确定使用绑定的范围。我对 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中,因为是不可绑定的箭头函数,所以x
和this.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.