做网站企业,常州软件开发公司,hao123网址导航,电子商务网站策划书3500字本篇将从JS的执行上下文开始#xff0c;去理解#xff1a;变量提升、 栈式调用、作用域和闭包。
参考#xff1a; 浏览器工作原理与实践
JS执行上下文
执行上下文是 JavaScript 执行一段代码时的运行环境#xff0c;比如调用一个函数#xff0c;就会生成这个函数的执行…本篇将从JS的执行上下文开始去理解变量提升、 栈式调用、作用域和闭包。
参考 浏览器工作原理与实践
JS执行上下文
执行上下文是 JavaScript 执行一段代码时的运行环境比如调用一个函数就会生成这个函数的执行上下文确定该函数在执行期间用到的诸如 this、变量环境、词法环境、外部环境引用等。
JS引擎执行JS代码分为两部分第一部分是编译、第二部分才是执行在编译阶段会做变量提升等操作生成JS执行上下文。 JS执行上下文中包含变量环境变量提升的变量都存储在这里面包括用户声明的变量以及函数声明变量里面还包括指向外部变量环境的引用作用域链查找、词法环境存储块级变量声明即const\let声明的量在生成了执行上下文后才会继续执行JS可执行的代码。
执行时需要从作用域中查询某个变量具体查询办法是沿着词法环境的栈顶向下查询如果在词法环境中的某个块中查找到了就直接返回给 JavaScript 引擎如果没有查找到那么继续在变量环境中查找。
showName()
console.log(myname)
showName1()var myname !!!
function showName() {console.log(函数showName被执行);
}
var showName1 function () {console.log(函数showName1被执行);
}// 输出
函数showName被执行
undefined
Error:showName1 is not a function如果showName1声明 var改成const Error:showName1 is not defined
说明 变量的生成涉及到 声明、赋值两个阶段。在声明阶段JS引擎会把变量和函数的声明提升到代码开头执行因此showName可以被执行myname被默认赋值为undefined但是showName1是一个变量赋值它一开始只是提升了声明因此showName1是undefined会报错not a function。
var的创建和初始化被提升赋值不会提升。 let的创建被提升初始化和赋值不会提升。 function的创建、初始化和赋值都被提升。
变量提升是指在 JavaScript 代码执行过程中JavaScript 引擎把变量的声明部分和函数的声明部分提升到代码开头的“行为”。变量被提升后会给变量设置默认值这个默认值就是我们熟悉的 undefined。变量提升操作并不会直接在代码里显现出来它是在JS代码的编译阶段完成的。
为什么要引入块级作用域 因为会存在着变量覆盖、无法自动回收全局变量导致占用内存 等设计缺陷所以 ES6 引入了块级作用域关键字来解决这些问题。
作用域
作用域是指在程序中定义变量的区域该位置决定了变量的生命周期。通俗地理解作用域就是变量与函数的可访问范围即作用域控制着变量和函数的可见性和生命周期。 作用域在编码时就确定了, 不会再变化可以用于隔离变量, 在不同作用域定义同名的变量不冲突。
作用域链:多个嵌套的作用域形成的由内向外的结构, 用于查找变量
分类:
全局作用域全局作用域中的对象在代码中的任何地方都能访问其生命周期伴随着页面的生命周期。函数作用域函数作用域就是在函数内部定义的变量或者函数并且定义的变量或者函数只能在函数内部被访问。函数执行结束之后函数内部定义的变量会被销毁。块级作用域。
区别作用域与执行上下文
作用域: 静态的, 编码时就确定了(不是在运行时), 一旦确定就不会变化了 执行上下文: 执行代码时在编译阶段动态创建, 当执行结束消失 联系: 执行上下文环境是在对应的作用域中的
作用域链
function bar() {console.log(myName)
}
function foo() {var myName 极客邦bar()
}
var myName 极客时间
foo()分析
答案是会输出极客时间。 为什么bar查询的作用域链不会指向foo的作用域链而是指向全局 因为作用域链的生成由函数声明的位置决定和调用位置、调用栈无关。 要回答这个问题你还需要知道什么是词法作用域。 这是因为在 JavaScript 执行过程中其作用域链是由词法作用域决定的。 词法作用域词法作用域就是指作用域是由代码中函数声明的位置来决定的所以词法作用域是静态的作用域通过它就能够预测代码在执行过程中如何查找标识符。 块级作用域
function bar() {var myName 极客世界let test1 100if (1) {let myName Chrome浏览器console.log(test)}
}
function foo() {var myName 极客邦let test 2{let test 3bar()}
}
var myName 极客时间
let myAge 10
let test 1
foo()分析 顺序由图中所示
可以由图里知道一个变量 作用域链会先查词法环境、再查变量环境接下来顺着外部引用依次查询词法环境、变量环境。 因此会输出1