第一个和第三个”this”指向到的是对象c,而第二个在setname中的this,指向的则是window object (global object),而这也就是为什么setname这个function没办法帮我们修改对象c中name属性的名称,因为”this”根本没指向到对象c。
而许多人都认为,这是JavaScript的一个bug。
那么我们可以怎么做
那么碰到上述的这个例子时,我们可以怎么做来避免指向到不同的对象呢?
许多人的解法是这样的,因为我们知道对象都是用的引用的方式,所以我们可以这样做
STEP 1
我们在整个函数的最上面加上一行var self = this
(有些人会用var that = this
)。由于引用的特性,self和this会指向到同一个对象,而this指向对象c,所以self一样会指向对象c。
STEP 2
接着,把方法log内原本使用的”this”都改成”self”,这样做可以确保self指向到的是c对象而不用担心会像上面的例子一样指向到错误的对象。
结果也如同我们预期的,在第二次console.log(self)的时候,就再次替换了对象c中name属性的值。
总结
让我们来总结一下:
如果我们是在全局环境建立函数并打印this,这时候this会指向到全局对象,也就是window对象。
如果我们是在对象里面创建函数,也就是方法(method)的情况时,这时候的this一般就会指向到包含这个方法的对象(之所以说”一般”是因为除了上述bug的情况之外)。
碰到method中可能会有不知道this指向到什么的情况时,为了避免不必要的错误,我们可以在method中的最上面建立一个变量,去把它指定成this(var self = this)。
4.如果真的还是不知道那个情况下的this会指向到什么,就console.log出来看看吧!
示例代码
// function statement function a(){ console.log(this); this.NewVariable = "Create a new property"; } a(); console.log(NewVariable); var c = { name:"The C object", log: function(){ var self = this; self.name = "Updated object C name"; console.log(self); var setname = function(newname){ self.name = newname; console.log(self); } setname("New name for object c"); console.log(self) } } c.log();