变量提升(Hoisting)
所谓的变量提升,是指在 JavaScript 代码执行过程中,JavaScript 引擎把变量的声明部分和函数的声明部分提升到代码开头的“行为”。变量被提升后,会给变量设置默认值,这个默认值就是我们熟悉的 undefined。
执行流程
编译阶段

var a = 2function add(b,c){return b+c}function addAll(b,c){var d = 10result = add(b,c)return a+result+d}addAll(3,6)

函数执行上下文是函数被调用的时候才会被创建的,js 引擎会编译函数,将函数的执行上下文压入栈中
栈溢出(stack overflow)
块级作用域
作用域(scope)
作用域是指在程序中定义变量的区域,该位置决定了变量的生命周期。通俗地理解,作用域就是变量与函数的可访问范围,即作用域控制着变量和函数的可见性和生命周期。
JS 是如何支持块级作用域的
级作用域就是通过词法环境的栈结构来实现的,而变量提升是通过变量环境来实现,通过这两者的结合,JavaScript 引擎也就同时支持了变量提升和块级作用域了。
作用域链和闭包
作用域链
每个执行上下文中都有 outer,它指向定义时所在的执行上下文, outer 将不同的执行上下文串联起来,形成作用域链 JavaScript 语言的作用域链是由词法作用域决定的,而词法作用域是由代码结构来确定的。
function bar() {console.log(myName)}function foo() {var myName = "极客邦"bar()}var myName = "极客时间"foo()
词法作用域
词法作用域就是指作用域是由代码中函数声明的位置来决定的,所以词法作用域是静态的作用域,通过它就能够预测代码在执行过程中如何查找标识符。 词法作用域是代码编译阶段就决定好的,和函数是怎么调用的没有关系。
闭包
在 JavaScript 中,根据词法作用域的规则,内部函数总是可以访问其外部函数中声明的变量,当通过调用一个外部函数返回一个内部函数后,即使该外部函数已经执行结束了,但是内部函数引用外部函数的变量依然保存在内存中,我们就把这些变量的集合称为闭包。
function foo() {var myName = "极客时间"let test1 = 1const test2 = 2var innerBar = {getName:function(){console.log(test1)return myName},setName:function(newName){myName = newName}}return innerBar}var bar = foo()bar.setName("极客邦")bar.getName()console.log(bar.getName())
this
this 是和执行上下文绑定的
