本文内容:

JavaScript闭包概念以及应用

变量作用域

全局变量

image-20200606154108463

在函数体外定义的变量为全局变量(即window对象),任何函数都可以直接访问全局变量中定义的变量

局部变量

image-20200606154533658

很明显,定义在函数内部的变量为函数私有变量,在函数内部可以被访问到,而在外部是不可以访问到函数内部定义的变量

函数内部变量一定要通过var进行声明!

image-20200606154618263

但这里需要注意的是,在局部变量的声明当中一定要使用var进行变量声明,否则声明的为全局变量,函数内外都可以访问到

如何访问函数内部变量?

由于JavaScript函数的特性,父函数中定义的子函数对于父函数的属性都是可见的,反之父函数对于子函数内部的变量是不可知,这个概念和定义在全局域中的函数不可被外部访问到内部变量的道理是一致的

举个例子:

image-20200606155235492

反之不可以

image-20200606155400209

但这里有个特点就是,既然子函数可以读取到父函数的变量值,那么我们如果子函数当做父函数的返回值的话,效果如何呢?

image-20200606155735292

合在一起就是这个,简单理解一下就可以

image-20200606155943782

JavaScript闭包

「闭包」,是指拥有多个变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分。

上面提到的func_2函数就是我们闭包了

这里套用阮一峰的一个例子

function f1(){

    var n=999;

    nAdd=function(){n+=1}

    function f2(){
      console.log(n);
    }

    return f2;

  }

  var result=f1();

  result(); // 999

  nAdd();

  result(); // 1000

image-20200606180855282

这里给的解释是f2为闭包函数,其中f1函数返回值为f2,从而可以访问到f1中的内部变量n,这里由于var result=f1();的存在,使得f2成为了一个全局变量,在内存中持续存在,从而不会被浏览器的回收机制给回收。

其中有一点,nAdd=function(){n+=1},这个由于没有使用var声明,所以ndd实际上为全局变量,这样使得在每次调用nAdd()时,都会对函数内部的变量进行修改

this关键字

https://www.quirksmode.org/js/this.html

function doSomething() {
this.style.color = '#cc0000';
}

image-20200607123716078

如果嵌套函数作为函数调用,其this值不是全局对象(非严格模式下)就是undefined(严格模式下); 如果嵌套函数作为方法调用,其this值指向调用它的对象

element.onclick = doSomething;

该函数将全部复制到onclick属性(现在变成方法)。因此,如果执行事件处理程序,则this引用HTML元素,并且该元素将 color被更改

image-20200607124938299

如果作为函数调用

<element onclick="doSomething()">

这时候this指向的是window对象,这个肯定不会存在style.color属性的,所以就会报错

image-20200607125205921

区别

element.onclick = doSomething;
console.log(element.onclick)

得到结果是

function doSomething()
{
this.style.color = '#cc0000';
}

而如果作为函数引用来使用

<element onclick="doSomething()">
console.log(element.onclick)

得到的结果是

function onclick()
{
doSomething()
}

可以明显看到区别所在

几个思考题

var name = "The Window";

var object = {
name : "My Object",

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

}

};

alert(object.getNameFunc()());

image-20200606183837220

这个的坑点在于理解this的作用域

所以这里指向的是全局变量name,打印出The Window

var name = "The Window";

  var object = {
    name : "My Object",

    getNameFunc : function(){
      var that = this;
      return function(){
        return that.name;
      };

    }

  };

  alert(object.getNameFunc()());

这个我认为是吧this的结果保存到that之后,然后通过返回that.name,这个实际上返回的是作为object对象的name,调用的是局部变量值object.name