javascript关于this对象,在闭包函数中为什么会引用全局变量

查看:86
本文介绍了javascript关于this对象,在闭包函数中为什么会引用全局变量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问 题

解决方案

this是跟著函式呼叫而产生的,它的范围是以函式为界限,谁(某物件)呼叫了这个函式,谁(某物件)就是this,与函式是在全域定义或物件字面定义无关,与呼叫函式是谁才有关。总个来说明,作用域是静态的,但this的建立却是动态的。

所以,像这个呼叫:

object.getNameFunc()

getNameFunc函式来说,this的确是object,也就是说当你的程式码改为下面的写法,就可以获得object.name,因为此时的this相当于object:

var object = {
  name:'bb',
  getNameFunc2: function(){
    return this.name;
  }
}

console.log(object.getNameFunc2()); //bb

当函式中没有明确的呼叫它的对象,在旧的情况下,this值默认为为window物件也就是全域物件,在新的标准中或是用严格模式(strict code)时,是undefined,刚上面说过this是以函式为界限。所以你在内部(巢状)函式里的下面这个函式呼叫,很明显的它的this值必然是默认情况:

return function(){
       return this.name;
}();

你的结果会得到aa的值,是因为不在严格模式(strict code)下,如果在严格模式或较新式写法中,是会发生错误而无法得到值,因为呼叫者是undefined,也就是不存在。aa是属于全域变数,或是window物件中的变数值。

而由于上面的这些知识,你可以利用内部(巢状)函式能够取得外部函式的变数作用域的特点,也就是闭包的特性,这种特性是因为作用域的连锁而来。进一步来修正内部函式的this值,所以可以用下面的解决方式,用一个中继的变数来转介外部函式的this值,下面的改写中的that并非一定要叫这个名称,有人喜好用self_that,实际上都行:

var object = {
  name:'bb',
  getNameFunc: function(){
     var that = this
     return function(){
        return that.name;
     }();
  }
}

另一种改写方式是视情况使用函式的callbind,它们可以在第一个传参中使用一个物件,以此改变函式呼叫(或执行)的上下文,也就是this值。

var object = {
  name:'bb',
  getNameFunc: function(){
     return function(){
        return this.name;
     }.call(this);
  }
}

由上面的实作可得知,内部函式的闭包结构,并不会传递外部函式的this值,因为this的设计是以函式为界限。提外话是,你可能也想知道函式的隐藏arguments物件会不会被传递,答案是当然也不会。

最后,你可能不知道在物件里面可以呼叫物件本身,所以下面的写法也是可行的,但它与this无关,只是JavaScript里可以这样作而已:

var object = {
  name:'bb',
  getNameFunc: function(){
     return function(){
        return object.name;
     }();
  }
}

你可以说他是个设计缺陷但它也存在几十年了,与其等待改变或直接放弃,不如先了解是什么。

详细的内容可以参考小弟整理的ES6电子书,在gitbook上,繁体的供参考:

闭包: https://eyesofkids.gitbooks.i...

this: https://eyesofkids.gitbooks.i...

这篇关于javascript关于this对象,在闭包函数中为什么会引用全局变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆