“ this”的绑定和“ this”的调用站点

时间:2019-09-13 19:58:23

标签: javascript object binding 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返回未定义,但是如果在其调用站点是声明a的位置,它是否不能访问变量a

2 个答案:

答案 0 :(得分:0)

this中的foo()是指在其中被调用的上下文,在代码段中是在没有定义变量a的全局上下文中被调用的,因此您得到undefined

您还使用a声明了let,这创建了一个块范围变量。如果您使用a在函数外部声明了var,它将在全局范围内创建一个变量。

在我的代码段中,我创建了一个具有两个属性afoo方法的对象。现在,如果您在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与您期望的不同以及如何处理它的原因。