程序员web之路让前端飞

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

2019-02-27  本文已影响7人  alanwhy

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

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

函数执行.png

闭包

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

但是在JS中闭包则是

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

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

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

执行上下文在ES3中:

在ES5中

在ES2018中

来个例子:

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

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

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的作用域:

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执行(二):闭包和执行上下文到底是怎么回事?

上一篇下一篇

猜你喜欢

热点阅读