【十二】JavaScript执行(二):闭包和执行上下文到底是怎么回事?

所有前端体系的集合链接:web之路

这次我们来了解一下网上有不同的名字的知识,如:

  • 闭包
  • 作用域链
  • 执行上下文
  • this 值

以上其实都是指函数执行过程的相关知识,如图:

12877063-52c7ea2d3512c573.png
函数执行.png

闭包

在古典的闭包定义下,闭包分为两个部分

  • 环境部分
    • 环境
    • 标识符列表
  • 表达式部分

但是在JS中闭包则是

  • 环境部分
    • 环境:函数的词法环境(执行上下文的一部分)
    • 标识符列表:函数中用到的未声明的变量
  • 表达式部分:函数体

这里要说一下,JS的执行上下文或者作用域(scope,ES3中规定的执行上下文的一部分)这个概念不是闭包

执行上下文:执行的基础设施

JS中与闭包“环境部分”相对应的术语是“词法环境”,词法环境只是JS执行上下文的一部分

执行上下文在ES3中:

  • scope:作用域,常常也被叫做作用域链
  • variable object:变量对象,用于存储变量的对象
  • this value: this值

在ES5中

  • lexical environment:词法环境,当获取变量时使用
  • variable environment:变量环境,当声明变量时使用
  • this value:this 值

在ES2018中

  • lexical environment:词法环境,当获取变量或者this值时使用
  • variable environment:变量环境,当声明变量时使用
  • code evaluation state:用于恢复代码执行位置
  • Function:执行的任务时函数时使用,表示正在被执行的函数
  • ScriptOrModule:执行的任务时脚本或者模块时使用,表示正在被执行的代码
  • Realm:使用的基础库和内置对象实例
  • Generator:仅生成器上下文有这个属性,表示当前生成器

来个例子:

var b = {}
let c = 1
this.a = 2;

想要执行上面的代码,就需要知道:

  • var把b声明到哪里
  • b表示哪个变量
  • b的原型时哪个对象
  • let 把c声明到哪里
  • this指向哪个对象

var 声明与赋值

var b = 1

通常我们认为它声明了b,并且为它赋值为1,var声明作用域函数执行的作用域。也就是说,var 会穿透for、if 等语句。

在没有let的旧JavaScript时代,诞生了一个技巧,叫做:立即执行的函数表达式(IIFE),通过创建一个函数, 并且立即执行,来构造一个新的域,从而控制var的范围。

由于语法规定了function 关键字开头是函数声明,所以要想让函数变成函数表达式,我们必须得加点东西,最常见的做法是加括号。

(function(){
    var a;
    //code
}());


(function(){
    var a;
    //code
})();

但是,括号有个缺点,那就是如果上一行代码不写纷号,括号会被解释为上一行代码最末的函数调用,产生完全不符合预期,并且难以调试的行为,加号等运算符也有类似的问题。所以一些推荐不加分号的代码风格规范,会要求在括号前面加上分号。

;(function(){
    var a;
    //code
}())


;(function(){
    var a;
    //code
})()

比较推荐的写法是用void关键字,即:

void function(){
    var a;
    //code
}();

let

let 是 ES6 开始引入的新的变量声明模式
let的作用域:

  • for
  • if
  • switch
  • try/catch/finally

Realm

在最新的标准(9.0)中,引入了新的Realm概念,看个例子

var b = {}

在ES2016之前的版本中,标准中甚少提到{}的原型问题,但在实际的开发中,iframe等方式创建的window环境并非罕见的操作,所以就有了Realm

Realm包含一组完整的内置对象,而且是复制谷关系

以下代码展示了浏览器环境中获取来自两个Realm对象,它们跟本土的Object做instanceOf时会产生差异

var iframe = document.createElement('iframe')
document.documentElement.appendChild(iframe)
iframe.src="javascript:var b = {};"

var b1 = iframe.contentWindow.b;
var b2 = {};

console.log(typeof b1, typeof b2); //object object

console.log(b1 instanceof Object, b2 instanceof Object); //false true

参考原文:JavaScript执行(二):闭包和执行上下文到底是怎么回事?

猜你喜欢

转载自blog.csdn.net/weixin_34376986/article/details/88231731
今日推荐