为什么 'this' 在方法 [javascript] 中结果为 'Undefined'

Why does 'this' result as 'Undefined' in method [javascript]

我正在研究这个内部对象方法的行为,但我卡在了一个输出上。

这是代码。

'use strict';

let obj, method;

obj = {
  go() { alert(this); }
};

obj.go();               // (1) [object Object]

(obj.go)();             // (2) [object Object]     QUESTION 2

(method = obj.go)();    // (3) undefined

(obj.go || obj.stop)(); // (4) undefined     ------> Doubt  <-------------------

那么如果第四个在逻辑上等同于第二个,为什么逻辑上的OR会导致上下文丢失?

第二部分

如有错误请指正

  1. 这个函数的计算方式是 called/invoked 函数 declaration/expression.

  2. 在箭头函数中,this 始终引用其封闭的父级。 [词法范围]

在情况 2 中,括号不会改变 () 左侧的函数引用值来自对象 属性 引用的事实。因此,函数调用的发生方式与情况 1 完全相同,对象引用绑定到 this.

然而,在情况 4 中,括号内的 || 评估导致该关系丢失;剩下的就是没有任何相关对象的函数引用。那是因为 || 的逻辑不关心函数引用来自对象 属性 查找这一事实,所以它的结果值只是函数引用 "naked".

关于你的后续问题,这两个断言的措辞都不正确。 this 的值确实取决于函数的调用方式,但这与函数的来源或声明方式无关。在箭头函数内部,this 的值不是对其词法父项的引用,它与词法父项中 this 的值相同。

实际上,# 的 3 和 4 return [object Window]

查看评论:

let obj, method;

obj = {
  go() { alert(this); }
};

obj.go();               // [object Object] represents obj

(obj.go)();             // [object Object] represents obj

(method = obj.go)();    // [object Window] because the go method is not running in the context of obj

(obj.go || obj.stop)(); //  Same as above

@Pointy 已经回答了你的问题。只是为了好玩:了解你现在所知道的,你可以让你的 obj.go 方法在它自己的范围内达到 运行,用箭头函数表达式包装:

let obj, method, otherMethod, m2;

obj = {
  foo: `obj.foo here, saying: done`,
  go(txt = ``) { console.log(`obj.go here, called as: ${txt} => ${this.foo}`); }
};
(txt => obj.go(txt))(`(txt => obj.go(txt))([...])`);
(method = txt => obj.go(txt))(`(method = txt => obj.go(txt))([...])`);
(obj.go && 
  (txt => obj.go(txt)) || 
  obj.stop)(`(obj.go && txt => obj.go(txt) || obj.stop)([...])`);

// or use a wrapper (factory function)
const wrap = (...[obj, method, txtArg]) => () => obj[method](txtArg);
(otherMethod = wrap(obj, `go`, `(otherMethod = wrap(obj, \`go\`, \`[...]\`))()`))();

// or make `go` a getter and that getter a factory function
let otherObj = {
  foo: `and hithere, here's otherObj.foo`,
  get go() { return txt => 
    console.log( `otherObj.go here, called as: ${txt} => ${this.foo}` ); }
};

(m2 = otherObj.go)(`(m2 = otherObj.go)([...])`);
.as-console-wrapper { top: 0; max-height: 100% !important; }