闭包和作用域链,是咱们在今天要学习的内容,也是前端开发中比较常用的知识点,闭包是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时我们所能直接访问的那个作用域对象。
如前面所说,当函数返回没有被引用的时候,就会被垃圾回收器回收。但是对于闭包(函数嵌套是形成闭包的一种简单方式)呢,即使外部函数返回了,函数对象仍会引用它被创建时的作用域对象。
热点新闻
前端开发技术库