当前位置: IT培训 > HTML5培训 > 前端开发 > JS > javascript闭包及作用域链
javascript闭包及作用域链 时间:2017-08-10     来源:JS开发教程文章汇总

闭包和作用域链,是咱们在今天要学习的内容,也是前端开发中比较常用的知识点,闭包是Javascript中的难点,也是它的一个特点,很多的应用的实现都需要闭包。

什么是闭包?咱们先看一下闭包的概念,闭包指可以访问另外一个函数作用域中的变量的函数这概念有点绕,拆分一下。从概念上说,闭包有两个特点:

1、函数

2、能访问另外一个函数作用域中的变量

在ES6之前,Javascript只有函数作用域,没有块级作用域。每个函数都是有一个单独的作用域,即外部是访问不到函数作用域中的变量。

function getName() {

var name = "张三";

console.log(name); //"张三"

}

function displayName() {

console.log(name); //报错

}

但是为了得到张三的名字,我们可以把代码改成这样:

functiongetName() {

varname = "张三";

functiondisplayName() {

console.log(name);

}

returndisplayName;

}

var name= getName();

name()//"名字"

关于闭包呢,再说三点:

1、闭包可以访问当前函数以外的变量

functiongetOuter(){

var date = '815';

function getDate(str){

console.log(str + date); //访问外部的date

}

return getDate('今天是:'); //"今天是:815"

}

getOuter();

getDate是一个闭包,该函数执行时,会形成一个作用域A,A中并没有定义变量date,但它能在父一级作用域中找到该变量的定义。

2、即使外部函数已经返回,闭包仍能访问外部函数定义的变量

function getOuter(){

var date = '815';

function getDate(str){

console.log(str + date); //访问外部的date

}

return getDate; //外部函数返回

}

var today = getOuter();

today('今天是:'); //"今天是:815"

today('明天不是:'); //"明天不是:815"

3、闭包可以更新外部变量的值

function updateCount(){

var count = 0;

function getCount(val){

count = val;

console.log(count);

}

return getCount; //外部函数返回

}

var count = updateCount();

count(815); //815

count(816); //816

下面咱们来看我们今天的下一个知识:作用域链。

为什么闭包就能访问外部函数的变量呢?这就要说说Javascript中的作用域链了。

如果没有找到,就去父作用域找,直到找到该变量的标示符或者找不到,这就是作用域链。

作用域链和原型继承有点类似,但又有小区别:如果去查找一个普通对象属性的时候,如果在当前对象中和其原型中都找不到的时候,就会返回undefined;但是如果查找的属性在作用域链中不存在的话就会抛出错误。

作用域链的顶端是全局对象。对于全局环境中的代码,作用域链只包含一个元素:全局对象。所以,在全局作用域中定义变量的时候,变量会被定义在全局对象里面。我们调用函数的时候,作用域链里面就会包含多个作用域对象。

接下来我们通过例子来学习下作用域链。

var foo = 1;

var bar = 2;

改动一下代码,创建一个没有函数嵌套的函数:

var foo = 1;

var bar = 2;

function test() {

var a =1;

var b =2;

var foo= 3;

console.log("insidetest");

}

console.log("outside");

//-- and then, call it:

test();

在我们定义了一个test函数的时候,函数的名称test就被加到了当前的作用域对象中,当做当前作用域对象的一个属性,并且这个变量引用的是一个函数对象。我们所关心的一个属性就是内部属性[[scope]]。[[scope]]属性在这里就是全局对象。

当test函数被调用的时候,新的作用域对象被创建。这个作用域对象中包含test函数所定义的本地变量,以及其参数。这个新的作用域对象的父作用域对象就是在运行test时我们所能直接访问的那个作用域对象。

如前面所说,当函数返回没有被引用的时候,就会被垃圾回收器回收。但是对于闭包(函数嵌套是形成闭包的一种简单方式)呢,即使外部函数返回了,函数对象仍会引用它被创建时的作用域对象。

X