`this` 的绑定和调用站点
`this` binding and call-site of `this`
函数是否可以访问其调用站点中的所有信息?
我认为也许某个函数可以访问其调用站点范围,否则我可能会弄错,因此非常感谢您的反馈和解释。
function bar() {
// call-stack is: `bar`
// so, our call-site is in the global scope
let a = “heyo”;
console.log( “bar” );
foo(); // ← call-site for `foo`
}
function foo() {
// call-stack is: `bar` -> `foo`
// so, our call-site is in `bar`
console.log( “foo “ + this.a );
}
bar(); // ← call-site for `bar`
这里,this.a returns没有定义,但是如果它的调用点是声明a
的地方,它不应该可以访问变量a
吗?
foo()
中的this
指的是调用它的上下文,在片段中它是在没有定义变量a
的全局上下文中调用的所以你得到 undefined
。
您还使用 let
声明了 a
,这会创建一个块作用域变量。如果您使用 var
在函数外部声明 a
,它将在全局范围内创建一个变量。
在我的代码片段中,我创建了一个具有两个属性 a
和 foo
方法的对象。现在,如果您在 obj
的上下文中调用 obj.foo()
方法,this
将指向 obj
对象,因为我使用 [=18= 声明了 a
] 在全局调用 foo()
时将从全局范围打印 a
的值:
var a = "from global";
function bar() {
//lexical context is global
//let defines a variable in the enclosing scope
let a = "heyo";
console.log( "bar" );
//foo is called within the global context, so this points to global object.
foo();
let obj = {a : "from obj", foo};
// or foo.bind(obj); which sets the this context
//now foo is called in the context of object "obj" so this points to obj
obj.foo();
}
function foo() {
console.log( "foo " + this.a );
}
bar();
首先,提出的问题根本不包含 this
,这很有趣,因为它是所提供问题的一个神奇例外。
JavaScript 是词法范围的。也就是说,函数可以访问它们 定义的范围 ,但不能访问当前堆栈任意位置的值。
const rememberX = (x) => () => x;
// a function that takes a value and returns a function
// when the inner function is called, it returns the value
let x = 5;
let x42 = rememberX(42);
let x10 = rememberX(10);
x = 20;
x42(); // 42
x10(); // 10
词法作用域提供了闭包的概念,这就是上述工作的原因。这使得它在传统情况下不太像其他语言,而更像是一种函数式编程语言。
有趣的是,this
是打破这种模式的唯一价值。它是异常延迟绑定的,并且在执行的那一刻就确定了。
class Person {
constructor (name) {
this.type = "person";
this.name = name;
}
sayHi () {
console.log(`${this.name}, the ${this.type}, says “Hi”.`);
}
}
const bob = new Person("Bob");
bob.sayHi(); // "Bob, the person, says “Hi”."
const spot = {
type: "dog",
name: "Spot",
sayHi: bob.sayHi
};
spot.sayHi(); // "Spot, the dog, says “Hi”."
bob.sayHi.apply({
type: "ape",
name: "Grape"
}); // "Grape, the ape, says “Hi”."
// apply is a method that all functions have,
// which sets `this` for this invocation
const bind = function (method, overriddenThis) {
return function (...args) {
return method.apply(overriddenThis, args);
};
};
// bind also exists as a method on functions,
// to prevent `this` from being overwritten, using closure
const sayHi = bind(bob.sayHi, bob);
sayHi.apply(spot); // "Bob, the person, says “Hi”."
这就是您的基于堆栈的调用无法按预期工作的原因,为什么 this
与您的预期不同,以及如何处理它。
函数是否可以访问其调用站点中的所有信息?
我认为也许某个函数可以访问其调用站点范围,否则我可能会弄错,因此非常感谢您的反馈和解释。
function bar() {
// call-stack is: `bar`
// so, our call-site is in the global scope
let a = “heyo”;
console.log( “bar” );
foo(); // ← call-site for `foo`
}
function foo() {
// call-stack is: `bar` -> `foo`
// so, our call-site is in `bar`
console.log( “foo “ + this.a );
}
bar(); // ← call-site for `bar`
这里,this.a returns没有定义,但是如果它的调用点是声明a
的地方,它不应该可以访问变量a
吗?
foo()
中的this
指的是调用它的上下文,在片段中它是在没有定义变量a
的全局上下文中调用的所以你得到 undefined
。
您还使用 let
声明了 a
,这会创建一个块作用域变量。如果您使用 var
在函数外部声明 a
,它将在全局范围内创建一个变量。
在我的代码片段中,我创建了一个具有两个属性 a
和 foo
方法的对象。现在,如果您在 obj
的上下文中调用 obj.foo()
方法,this
将指向 obj
对象,因为我使用 [=18= 声明了 a
] 在全局调用 foo()
时将从全局范围打印 a
的值:
var a = "from global";
function bar() {
//lexical context is global
//let defines a variable in the enclosing scope
let a = "heyo";
console.log( "bar" );
//foo is called within the global context, so this points to global object.
foo();
let obj = {a : "from obj", foo};
// or foo.bind(obj); which sets the this context
//now foo is called in the context of object "obj" so this points to obj
obj.foo();
}
function foo() {
console.log( "foo " + this.a );
}
bar();
首先,提出的问题根本不包含 this
,这很有趣,因为它是所提供问题的一个神奇例外。
JavaScript 是词法范围的。也就是说,函数可以访问它们 定义的范围 ,但不能访问当前堆栈任意位置的值。
const rememberX = (x) => () => x;
// a function that takes a value and returns a function
// when the inner function is called, it returns the value
let x = 5;
let x42 = rememberX(42);
let x10 = rememberX(10);
x = 20;
x42(); // 42
x10(); // 10
词法作用域提供了闭包的概念,这就是上述工作的原因。这使得它在传统情况下不太像其他语言,而更像是一种函数式编程语言。
有趣的是,this
是打破这种模式的唯一价值。它是异常延迟绑定的,并且在执行的那一刻就确定了。
class Person {
constructor (name) {
this.type = "person";
this.name = name;
}
sayHi () {
console.log(`${this.name}, the ${this.type}, says “Hi”.`);
}
}
const bob = new Person("Bob");
bob.sayHi(); // "Bob, the person, says “Hi”."
const spot = {
type: "dog",
name: "Spot",
sayHi: bob.sayHi
};
spot.sayHi(); // "Spot, the dog, says “Hi”."
bob.sayHi.apply({
type: "ape",
name: "Grape"
}); // "Grape, the ape, says “Hi”."
// apply is a method that all functions have,
// which sets `this` for this invocation
const bind = function (method, overriddenThis) {
return function (...args) {
return method.apply(overriddenThis, args);
};
};
// bind also exists as a method on functions,
// to prevent `this` from being overwritten, using closure
const sayHi = bind(bob.sayHi, bob);
sayHi.apply(spot); // "Bob, the person, says “Hi”."
这就是您的基于堆栈的调用无法按预期工作的原因,为什么 this
与您的预期不同,以及如何处理它。