JavaScript执行流程
变量和函数在代码里的位置是不会改变的,而是在编译阶段被JavaScript引擎放入内存中

showName()
console.log(myname)
myname = '极客时间'

执行上下文是 JavaScript 执行一段代码时的运行环境,比如调用一个函数,就会进入这个函数的执行上下文,确定该函数在执行期间用到的诸如 this、变量、对象以及函数等。
- JavaScript 代码执行过程中,需要先做变量提升,而之所以需要实现变量提升,是因为 JavaScript 代码在执行之前需要先编译。
- 在编译阶段,变量和函数会被存放到变量环境中,变量的默认值会被设置为 undefined;在代码执行阶段,JavaScript
- 引擎会从变量环境中去查找自定义的变量和函数。 如果在编译阶段,存在两个相同的函数,那么最终存放在变量环境中的是最后定义的那个,这是因为后定义的会覆盖掉之前定义的。
Javascript中的栈
- 当 JavaScript 执行全局代码的时候,会编译全局代码并创建全局执行上下文,而且在整个页面的生存周期内,全局执行上下文只有一份。
- 当调用一个函数的时候,函数体内的代码会被编译,并创建函数执行上下文,一般情况下,函数执行结束之后,创建的函数执行上下文会被销毁。
- 当使用 eval 函数的时候,eval 的代码也会被编译,并创建执行上下文。
var a = 2
function add(){
var b = 10
return a+b
}
add()


栈
Javascript通过栈来管理执行上下文,成为执行上下文栈也叫调用栈。特点:后进先出
var a = 2
function add(b,c){
return b+c
}
function addAll(b,c){
var d = 10
result = add(b,c)
return a+result+d
}
addAll(3,6
- 创建全局上下文,将其压入栈底
- 调用addAll函数
- 当执行到 add 函数调用语句时,同样会为其创建执行上下文,并将其压入调用栈
- add函数返回


开发中查看函数调用栈关系

用trace函数查看栈关系

栈溢出
调用栈是有大小的,当入栈的执行上下文超出一定数目,JavaScript就会报栈溢出。尤其是写递归的时候。
function division(a,b){
return division(a,b)
}
console.log(division(1,2)

- 每调用一个函数,JavaScript 引擎会为其创建执行上下文,并把该执行上下文压入调用栈,然后 JavaScript 引擎开始执行函数代码。
- 如果在一个函数 A 中调用了另外一个函数 B,那么 JavaScript 引擎会为 B 函数创建执行上下文,并将 B 函数的执行上下文压入栈顶。
- 当前函数执行完毕后,JavaScript 引擎会将该函数的执行上下文弹出栈。
- 当分配的调用栈空间被占满时,会引发“堆栈溢出”问题
let和var
function foo(){
var a = 1
let b = 2
{
let b = 3
var c = 4
let d = 5
console.log(a)
console.log(b)
}
console.log(b)
console.log(c)
console.log(d)
}
foo()
第一步,编译并执行上下文

- 函数内部通过 var 声明的变量,在编译阶段全都被存放到变量环境里面了。
- 通过 let 声明的变量,在编译阶段会被存放到词法环境(Lexical Environment)中。
- 在函数的作用域内部,通过 let 声明的变量并没有被存放到词法环境中。



闭包

在 JavaScript 中,根据词法作用域的规则,内部函数总是可以访问其外部函数中声明的变量,当通过调用一个外部函数返回一个内部函数后,即使该外部函数已经执行结束了,但是内部函数引用外部函数的变量依然保存在内存中,我们就把这些变量的集合称为闭包。


this
当函数作为对象的方法调用时,函数中的 this 就是该对象; 当函数被正常调用时,在严格模式下,this 值是 undefined,非严格模式下 this 指向的是全局对象 window; 嵌套函数中的 this 不会继承外层函数的 this 值。

三种方式绑定执行上下文的值
- 通过函数的 call 方法设置
- 通过对象调用方法设置
var myObj = {
name : " 极客时间 ",
showThis: function(){
console.log(this)
}
}
myObj.showThis()
相当于
myObj.showThis.call(myObj)
注意
var myObj = {
name : " 极客时间 ",
showThis: function(){
this.name = " 极客邦 "
console.log(this)
}
}
var foo = myObj.showThis
foo()
- 在全局环境中调用一个函数,函数内部的 this 指向的是全局变量 window。
- 通过一个对象来调用其内部的一个方法,该方法的执行上下文中的 this 指向对象本身。
- 通过构造函数中设置
function CreateObj(){
this.name = " 极客时间 "
}
var myObj = new CreateObj()
// 相当于
var tempObj = {}
CreateObj.call(tempObj)
return tempObj