2017-01-25 11 views
2

jdfiddle:https://jsfiddle.net/2khtof8s/1/Uncaught (in promise) TypeError: Cannot read property 'someFunction' of undefinedなぜクラスでの短縮形関数の使用が "this"を未定義にするのでしょうか?

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チェーンエラーを - 私たちは、誰もがこの動作に任意の​​洞察力を持っていない理由を理解していないようですか?私たちが知る限り、相違はないはずです。

+0

可能な複製を[正しい\ 'をアクセスする方法この\ 'コールバックの内部?] (http://stackoverflow.com/questions/20279484/how-to-access-the-correct-this-inside-a-callback) –

答えて

4

インスタンスの関数への参照を渡すと、コンテキストが失われます。

instance.doSomething // just a reference 

は、文脈のない単なる参考情報です。あなたが参照

instance.doSomething.bind(instance) 

これはそれをこの方法を考えるのに役立つかもしれない:あなたがやろうとしている何をするためには、bindへの参照にコンテキストを必要としますinstance.doSomethingと言いますと、「私はinstanceです。これはdoSomethingのようなものです。あなたが私を呼び出すと、私は何を使用しますか?」

差はreferencingcallingです。

参考:(コンテキストを維持):

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);

+0

なぜ他のフォームはバインドを必要としないのですか? – Eva

+0

@Eva \tこれらは 'this'を参照していないためです。 –

+0

@エバ、私はいくつかの違いを説明しようと編集しました。しかし、それが呼び出されるときに使用する関数への参照であり、もう1つはまだそのコンテキストを使用しているその関数への呼び出しであるということです。 – KevBot

0

これは、以下のサンプルは、エラーがスローされます、同じ理由で動作しません呼び出す

instance.doSomething 

オブジェクトのプロパティである関数を別の変数に割り当てると、そのコンテキストが失われます。

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"

関連する問題