了解this
on 函数调用的隐式行为的关键在于了解引用类型如何工作。
的参考类型由两个部分组成(在ECMAScript中3),所述的基础对象和属性名称(在ECMAScript中5,它有一个第三部件的严格标志-I将谈论严格模式later- (1) )。
当被调用的功能,该this
值是通过获取参考的基础对象(由内部隐含地确定GetBase
操作)。
例如,在foo.bar
引用中,基础对象是foo
,属性名称是"bar"
:
foo.bar(); // `this` will point to `foo`
当您进行赋值时,引用丢失了,我们不再有基础对象和属性名称,我们只有一个值:
(f=foo.bar)(); // `this` will point to the global object
它不仅发生在赋值中,还会发生在使用内部GetValue
操作的其他操作中:
// `this` will point to the global object
(0, foo.bar)(); // The Comma Operator
(0 || foo.bar)(); // Binary Logical Operators
(1 && foo.bar)();
// etc..
例如,如果您用括号将引用括起来(正式称为The Grouping Operator),则不会发生这种情况:
(foo.bar)(); // `this` will point to `foo`
分组运算符(同样,括号 ;)不在GetValue
内部使用,这是以这种方式设计的,因为允许typeof
和delete
运算符与括号表达式一起使用:
delete (foo.bar);
如果使用分组运算符GetValue
,则delete
运算符将无法获取要删除属性的基础对象bar
。
回到隐含this
值,有一些棘手的情况,例如,使用with
语句:
with (foo) {
bar(); // `this` will refer to `foo` !
}
如您所见,bar();
在 with 块内部调用,仍会将this
值绑定到foo
对象。
该this
值不是从reference设置的,它来自语句引入的当前环境记录(我可能稍后会写一些关于它的内容)with
。
此外,您可能会注意到,对于non-references,该this
值将指向全局对象,例如:
(function () {})(); // this will point to the global object
我们只有一个值,而不是引用(请记住,引用是解析的名称绑定)。
(1)注意:在 ECMAScript 5 Strict Mode 上,该this
值将undefined
适用于所描述的所有情况,其中该this
值被隐式设置为 Global 对象。
之所以这样做是作为一种安全措施,主要是因为人们new
在调用构造函数时经常忘记使用运算符,从而导致不良行为和对全局范围的污染。
例如:
function Foo () {
this.prop = 'foo';
}
Foo(); // no `new` operator, boom!
正如您现在所知,Foo
引用没有直接的基础对象,this
它将指向全局对象,并且会无意中在其上创建一个属性。
在严格模式下,代码只会给你一个TypeError
,因为this
值是undefined
。
同样,您可能还记得一开始我提到引用类型有第三个组件,即strict
标志。
您的原始示例:
(f=foo.bar)();
甚至可能不适用于严格模式,因为不允许分配给未声明的标识符(例如f
似乎),(另一种避免全局对象污染的安全措施)。
更多信息: