为什么 '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会导致上下文丢失?
第二部分
如有错误请指正
这个函数的计算方式是 called/invoked 函数 declaration/expression.
在箭头函数中,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; }
我正在研究这个内部对象方法的行为,但我卡在了一个输出上。
这是代码。
'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会导致上下文丢失?
第二部分
如有错误请指正
这个函数的计算方式是 called/invoked 函数 declaration/expression.
在箭头函数中,
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; }