美文网首页前端你不进来看看?程序员Web前端之路
前端学习指南第二天:彻底理解作用域,作用域链和闭包

前端学习指南第二天:彻底理解作用域,作用域链和闭包

作者: HarryPang | 来源:发表于2017-03-22 13:51 被阅读159次

5作用域:作用域简单说就是函数和变量能够访问的范围,控制变量的可见性和生命周期。其中包含了局部作用域和全局作用域。

变量没有在函数内声明或声明的时候没有带var就是全局变量, 拥有全局作用域, window对象的所有属性拥有全局作用域;在代码的任何地方都可以访问,

函数内部声明并且以var修饰的变量就是局部变量, 只能在函数体内使用, 函数的参数虽然没有使用var但仍然是局部变量.

以下是比较让人迷惑的地方
javascript没用块级作用域,只有函数级作用域,这里要理解一下js的声明提前(声明提前:在函数内部,不管在哪里声明,其实他们都是统一被放在函数顶部被声明。所以通常的做法是在函数顶部统一声明变量。)。

console.log(a);//undefined,虽然var a =3,会提前这句声明,但是只会预解析到var a,并不会执行赋值操作 a=3,所以未定义
var a =3;
consloe.log(a);//3执行完赋值语句自然得到3

但我们可以模仿块级作用域

(function(){
//这里就是块级作用域,这其实也是立即执行函数
})

作用域链:
当代码在一个环境中执行时, 会创建变量对象的一个作用域链(scope chain)来保证对执行环境有权访问的变量和函数的有序访问. 作用域第一个对象始终是当前执行代码所在的环境变量对象(VO).

function a(x, y){
    var b = x + y;
    return b;
}

在函数a创建的时候它的作用域链值入全局对象, 全局对象中有所有全局变量.如下图所示(注意:图片只列举了全部变量中的一部分):


Paste_Image.png

如果执行环境是函数, 那么将其活动对象(activation object, AO)作为作用域链第一个对象, 第二个对象是包含环境, 下一个是包含环境的包含环境...

function a(x, y){
    var b= x + y;
    return b;
}
var t = a(5, 10);

这时候, var t = a(5, 10);语句的作用域链如下:


Paste_Image.png

在函数运行过程中, 标识符的解析是沿着作用域链一级一级搜索的过程, 从第一个对象开始, 逐级向上回溯(由下至上), 直到找到同名标识符为止, 找到后不再继续遍历, 找不到就报错.

闭包:

背景:
根据作用域和作用域链的原理,我们似乎不能在外部读取其它函数的内部变量。
闭包:
闭包就是能够读取其他函数内部变量的函数,在js中,只有函数内部的子函数才能读取局部变量,因此可以把闭包简单理解成“定义在一个函数内部的函数”。
只要存在调用内部函数的可能, JavaScript就需要保留被引用的函数, 而且JavaScript运行时需要跟踪引用这个内部函数的所有变量, 直到最后一个变量废弃, JavaScript的垃圾回收器才能释放相应的内存空间.
本质上,闭包是函数内外部的桥梁。
原理:
1.后台执行环境中,闭包的作用域链包含着自己的作用域、函数的作用域和全局作用域。
2.通常,函数的作用域和变量会在函数执行结束后销毁。
3.但是,当函数返回一个闭包时,这个函数的作用域将会一直在内存中保存到闭包不存在为止。
用途:
1.访问函数内部变量,就是实现面向对象的访问控制。也就是c++, c#, java等面向对象的private, public访问控制
2.将这些变量值始终保存在内存
缺点:
1.需要维护额外的作用域
2.过渡使用闭包会占用大量内存

for(var i=0; i<eles.length; i++){
    eles[i].onclick = function(){
        alert(i);
    }
}

每次点击eles alert的值都是length, 这代码中为eles绑定的click事件处理程序的作用域链是这样的:


Paste_Image.png

由于内部函数(click事件处理程序时刻有调用可能), 所以其作用域链不能被销毁(更别说本例中i在全局作用域中, 只能在页面关闭时销毁), i的值一直保持for循环执行完后的length的值, 所以每次触发onclick的时候才会alert length.

相关文章

  • 5分钟入门闭包

    理解闭包前先要理解两个概念:作用域和作用域链。一、作用域分为: 全局作用域 函数作用域 var a = 100 f...

  • JavaScript 函数闭包(colsure)

    理解闭包,你首先必须理解JS的变量作用域,JavaScript作用域和作用域链。 ES6之前,变量的作用域分为全局...

  • 2023-01-12

    变量提升调用栈块级作用域作用域链和闭包 闭包 => 作用域链(词法作用域) => 调用栈(栈溢出) => 上下文...

  • js 总结七07-19

    作用域 全局 局部 作用域链 闭包

  • 深入理解闭包(五)——作用域、作用域链和执行上下文

    原文地址:深入理解闭包(五)——作用域、作用域链和执行上下文 作用域,作用域链,执行上下文三者之间有着密切的关系,...

  • 作用域和闭包

    目录 概述 作用域编译过程词法作用域全局作用域函数作用域 闭包循环和闭包闭包的用途性能 总结 概述 作用域和闭包一...

  • js函数中的this

    前两篇文章“执行环境和作用域”和“js中的闭包”,我对谈了执行环境、作用域、作用域链和闭包的理解。但当牵涉到对象中...

  • js作用域、闭包

    闭包 闭包作用 全局 局部 作用域链

  • 执行上下文,词法作用域,作用域链,闭包

    执行上下文,词法作用域,作用域链,闭包

  • 2018-07-11

    深入理解闭包: 一、变量的作用域 要理解闭包,首先必须理解Javascript特殊的变量作用域。 变量的作用域无非...

网友评论

    本文标题:前端学习指南第二天:彻底理解作用域,作用域链和闭包

    本文链接:https://www.haomeiwen.com/subject/tjannttx.html