为什么速记函数与类一起使用导致“this”未定义?

时间:2017-01-25 19:04:36

标签: javascript

jdfiddle:https://jsfiddle.net/2khtof8s/1/

class TestClass {
    doSomething(){
        return Promise.resolve(this.someFunction('hello'))
    }

    someFunction( testVar ){
        return testVar;
    }
}

let instance = new TestClass();

// throws error
Promise.resolve()
    .then(instance.doSomething)
    .then(console.log)
    .catch(console.error);

// works
Promise.resolve()
    .then(() => instance.doSomething())
    .then(console.log);

// works
Promise.resolve()
    .then(function(){return instance.doSomething()})
    .then(console.log);

// works
function someFunc(){
    return instance.doSomething();
}

Promise.resolve()
    .then(someFunc)
    .then(console.log);

第一个Promise.resolve链出错Uncaught (in promise) TypeError: Cannot read property 'someFunction' of undefined - 我们似乎无法理解为什么,是否有人对这种行为有任何见解?我们可以说,似乎应该没有区别

2 个答案:

答案 0 :(得分:4)

当您传递对实例函数的引用时,上下文将丢失。

instance.doSomething // just a reference

只是一个没有上下文的引用。为了完成您要执行的操作,您需要bind参考的上下文:

instance.doSomething.bind(instance)

这可能有助于这样思考:

当您引用instance.doSomething时,请将其视为"我是instance,这是doSomething的样子,以及如果您调用我会使用的内容我"

区别在于referencingcalling

参考:

instance.doSomething

调用:(维护上下文):

instance.doSomething();



class TestClass {
  doSomething() {
    return Promise.resolve(this.someFunction('hello'))
  }

  someFunction(testVar) {
    return testVar;
  }
}

let instance = new TestClass();

// No longer throws error
Promise.resolve()
  .then(instance.doSomething.bind(instance))
  .then(console.log)
  .catch(console.error);




答案 1 :(得分:0)

由于以下示例引发错误的原因相同,这不起作用。 如果将作为对象属性的函数指定给另一个变量,则会丢失其上下文。



class Test {
  constructor() {
    this.foo = 'bar';
  }
  
  print() {
    console.log(this.foo);
  }
}

const test = new Test();

test.print();      // "bar"

const standalonePrint = test.print;
standalonePrint(); // throws




你可以通过手动绑定函数的上下文来解决这个问题



class Test {
  constructor() {
    this.foo = 'bar';
  }

  print() {
    console.log(this.foo);
  }
}

const test = new Test();

const standalonePrint = test.print;
const boundPrint = standalonePrint.bind(test);
boundPrint(); // "bar"