'this'是Javascript中的全局对象的情况

Pau*_*son 9 javascript

我正在玩不同的方法来调用一个函数,这个函数是Javascript中Object的一个属性,并查看哪个类型的调用将'this'设置为Object,并将'this'设置为Global Object.

这是我的测试代码:

var foo = {
  bar: function(){ 
    console.log('this:' + this);
  }
}

console.log('calling foo.bar()');
foo.bar();

console.log('\ncalling (foo.bar)()');
(foo.bar)();

console.log('\ncalling f=foo; f.bar()');
f = foo; f.bar();

console.log('\ncalling f=foo.bar; f()');
f = foo.bar; f();

console.log('\ncalling (f=foo.bar)()');
(f = foo.bar)();
Run Code Online (Sandbox Code Playgroud)

这就是结果:

calling foo.bar()
this:[object Object]

calling (foo.bar)()
this:[object Object]

calling f=foo; f.bar()
this:[object Object]

calling f=foo.bar; f()
this:[object global]

calling (f=foo.bar)()
this:[object global]
Run Code Online (Sandbox Code Playgroud)

我的问题是,为什么f=foo.bar; f();并将(f=foo.bar)();'this'指定为全局对象

CMS*_*CMS 10

知道this函数调用的隐式行为的关键在于知道引用类型是如何进行的.

参考类型由两个部分组成(在ECMAScript中3),所述的基础对象属性名称(在ECMAScript中5,它有一个第三部件的严格标志-I将谈论严格模式later- (1) ).

被调用的功能,该this值是通过获取参考的基础对象(由内部隐含地确定GetBase操作).

例如,在foo.bar引用中,基础对象foo,属性名称"bar":

foo.bar(); // `this` will point to `foo`
Run Code Online (Sandbox Code Playgroud)

当您执行赋值时,引用将丢失,我们不再具有基础对象属性名称,我们只有一个:

(f=foo.bar)(); // `this` will point to the global object
Run Code Online (Sandbox Code Playgroud)

它不会仅在分配时发生,而是与使用内部GetValue操作的其他操作一起发生:

// `this` will point to the global object    
(0, foo.bar)();   // The Comma Operator
(0 || foo.bar)(); // Binary Logical Operators
(1 && foo.bar)();
// etc..
Run Code Online (Sandbox Code Playgroud)

例如,如果用括号括起引用(正式称为分组运算符),则不会发生这种情况:

(foo.bar)(); // `this` will point to `foo`
Run Code Online (Sandbox Code Playgroud)

分组运算符(再次,括号;)不在GetValue内部使用,这是以这种方式设计的,因为允许typeofdelete运算符使用带括号的表达式:

delete (foo.bar);
Run Code Online (Sandbox Code Playgroud)

如果使用分组运算符GetValue,则delete运算符将无法获取基础对象的删除属性bar.

返回隐式this值,有一些棘手的情况,例如,使用with语句:

with (foo) {
  bar(); // `this` will refer to `foo` !
}
Run Code Online (Sandbox Code Playgroud)

如您所见,bar();在with块内部调用仍然会将this值绑定到foo对象.

this值不是从引用设置的,它来自当前的环境记录(我可能稍后会写一些关于它的内容)with.

此外,您可能会注意到,对于非引用,该this值将指向全局对象,例如:

(function () {})(); // this will point to the global object
Run Code Online (Sandbox Code Playgroud)

我们只有一个,而不是一个引用(请记住,引用是一个已解析的名称绑定).


(1)注意:在ECMAScript 5 严格模式下,该this值将undefined适用于描述的所有情况,其中this值隐式设置为Global对象.

这是一种安全措施,主要是因为人们new在调用构造函数时经常忘记使用运算符,导致不良行为和对全局范围的污染.

例如:

function Foo () {
  this.prop = 'foo';
}
Foo(); // no `new` operator, boom!
Run Code Online (Sandbox Code Playgroud)

正如您现在所知,Foo引用没有直接的基础对象,this将指向全局对象,并且它将无意中在其上创建属性.

在严格模式下,代码只会给你一个TypeError,因为this值是undefined.

另外你可能还记得在开头我提到过参考类型有第三个组件,即strict标志.

你原来的例子:

(f=foo.bar)();
Run Code Online (Sandbox Code Playgroud)

甚至可能不会在严格模式下工作,因为不允许对未声明的标识符(例如f 似乎)进行分配,(另一种避免全局对象污染的安全措施).

更多信息: