例如“this”是Javascript中的全局对象

前端之家收集整理的这篇文章主要介绍了例如“this”是Javascript中的全局对象前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我正在玩各种不同的方法调用一个 Javascript中的Object的属性,并查看哪个类型的调用将’this’设置为Object,并将’this’设置为全局对象.

这是我的测试代码

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

这就是结果:

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]

我的问题是,为什么f = foo.bar; F();和(f = foo.bar)();将’this’赋值为全局对象

解决方法

了解这个对函数调用的隐含行为的关键在于知道 Reference Type如何操作.

参考类型由两个组件(ECMAScript 3)组成,基础对象和属性名称(在ECMAScript 5中,它具有第三个组件严格标志 – 稍后将讨论严格模式(1)).

当一个function is invoked时,通过获取引用的基础对象(通过内部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运算符将无法获取一个基础对象去除属性栏.

回到隐含的这个值,有一些棘手的例子,例如使用with语句:

with (foo) {
  bar(); // `this` will refer to `foo` !
}

你可以看到,调用bar();在with块中,仍然将该值绑定到foo对象.

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

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

(function () {})(); // this will point to the global object

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

(1)注意:在ECMAScript 5严格模式下,对于所有这些值隐含设置为全局对象的情况,该值将不被定义.

这是作为一种安全措施,主要是由于人们经常忘记在调用构造函数时使用新的运算符,从而对全局范围造成不良的行为和污染.

例如:

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

如你所知,Foo引用没有直接的基础对象,这将指向全局对象,它将无意中创建一个属性.

在严格的模式下,代码只会给你一个TypeError,因为这个值将是未定义的.

同样你可能记得在一开始我提到参考类型有一个第三个组件,严格的标志.

你原来的例子:

(f=foo.bar)();

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

更多信息:

> Strict Mode

猜你在找的JavaScript相关文章