上周被一个超简单的问题困扰了很久:
当一个匿名函数作为callback被调用的时候,它的this
context是什么???
答:难道不是使用这个callback的函数么??
问:如果这个函数是通过new
关键字来实例化的呢?
答:呃…… 这个时候应该是这个实例本身?
答案是:
non-strict
mode : window
strict
mode: undefined
然而这个答案对于当时的我来说实在是太烧脑,
于是我花了两个工作天(所以其实并不是全天都在查资料啦)的时间来探究这个问题。
代码示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| var Person = function (name) { this.name = name; console.log(this); } Person.prototype.say = function (word, cb) { console.log(this.name); if(cb && typeof cb === 'function'){ cb(); } } var globalSam = new Person('global sam'); globalSam.say('hello', function() { console.log(this); }); var simpleObject = { keySam: new Person('key sam'), log: function(){ this.keySam.say('hey', function(){ console.log(this); }); } } simpleObject.log();
|
这让我想起了很久以前,自己看了一大堆资料以后,对this
的一个总结:
當不清楚this
的指向的時候,可以问自己一个问题:
「是谁(哪个object)调用了使用this
的方法?」
即
「方法被调用時,this
所依附的object是什么?」
再看我们的demo,是globalSam.say
和simpleOject.log
调用了作为callback的匿名函数。而globalSam
和simpleObject
其实是window.globalSam
和window.simpleObject
,所以我们会log出那样的结果。
至此,也可以得出一个推论:任何匿名函数,只要在代码中没有明确地绑定context,他们的this
都会指向全局(global context)或者浏览器的window
对象。而当代码是在js的strict
mode下执行的,它们的context就会是undefined
。
现在,如果我们这样改写上面的例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| var Person = function (name) { this.name = name; } Person.prototype.say = function (word, cb) { console.log(this.name); if(cb && typeof cb === 'function'){ console.log('====== logging cb ======'); cb(); console.log('====== logging do something ======'); this.doSomething = cb; this.doSomething(); } } var globalSam = new Person('global sam'); globalSam.say('hello', function() { console.log(this); }); var simpleObject = { keySam: new Person('key sam'), logKeySam: function(){ this.keySam.say('hey', function(){ console.log(this); }); } } simpleObject.logKeySam();
|
参考文章:
[1] Understanding Scope and Context in JavaScript
[2] JAVASCRIPT: ANONYMOUS FUNCTIONS