函数可以访问其呼叫站点中的所有信息吗?
我认为某个函数可以访问其调用站点范围,否则我可能会弄错,因此,我希望您能提供反馈和解释。
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返回未定义,但是如果在其调用站点是声明a
的位置,它是否不能访问变量a
?
答案 0 :(得分:0)
this
中的foo()
是指在其中被调用的上下文,在代码段中是在没有定义变量a
的全局上下文中被调用的,因此您得到undefined
。
您还使用a
声明了let
,这创建了一个块范围变量。如果您使用a
在函数外部声明了var
,它将在全局范围内创建一个变量。
在我的代码段中,我创建了一个具有两个属性a
和foo
方法的对象。现在,如果您在obj.foo()
的上下文中调用obj
方法,则this
将指向obj
对象,并且由于我使用{{1}声明了a
} var
的全局调用中的}将在全局范围内打印foo()
的值:
a
答案 1 :(得分:0)
首先,提出的问题根本不包含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
与您期望的不同以及如何处理它的原因。