我正在玩不同的方法来调用一个函数,这个函数是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内部使用,这是以这种方式设计的,因为允许typeof和delete运算符使用带括号的表达式:
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 似乎)进行分配,(另一种避免全局对象污染的安全措施).
更多信息:
| 归档时间: |
|
| 查看次数: |
550 次 |
| 最近记录: |