浏览器中的js的执行机制¶
js中的变量提升¶
showName();
console.log(myname);
var myname = 'dou';
function showName(){
console.log("showName函数被执行")
}
// "showName函数被执行"
// undefined
- 在执行过程中,如果使用了未声明的变量,那么JS的执行会报错
- 在一个变量定义之前使用它,不会出错,但是该变量的值会变成undefined,而不是定义时的值
- 在一个函数定义之前使用它,不会出错,且函数能正确执行
同样的方式,为什么变量和函数的处理方式不同?
模拟上述代码的执行过程:
/** 变量提升部分*/
var myname = undefined
// 函数的定义也会被提升
function showName(){
console.log("showName函数被执行")
}
// 代码执行部分
showName();
console.log(myname);
myname = 'dou';
JavaScript代码的执行流程¶
一段JavaScript代码→编译阶段→执行阶段
编译阶段¶
编译阶段和变量提升存在什么关系?
变量提升部分
/** 变量提升部分*/
var myname = undefined
// 函数的定义也会被提升
function showName(){
console.log("showName函数被执行")
}
执行代码部分
showName();
console.log(myname);
myname = 'dou';
在编译阶段主要是生成两部分内容:
执行上下文(全局执行上下文和函数的执行上下文)和可执行代码
执行上下文是JavaScript执行一段代码时的运行环境,比如调用一个函数,就会进入这个函数的执行上下文,确定该函数在执行期间用到的诸如this、变量、对象以及函数等。
全局变量环境对象--就是用于存储变量提升后的声明的数据
VariableEnvironment
myname->undefined
showName->function(){...}// 堆的内存地址,其中存储的是函数体内容
showName指向堆中的一个地址,其中存储的函数体内容
执行阶段¶
JavaScript引擎开始执行可执行代码,并且按照顺序一步一步的执行
代码中如果出现相同的变量或者函数怎么办?¶
function showName(){
console.log("max")
}
showName()
function showName(){
console.log("kaka")
}
showName()
// kaka
// kaka
分析:两个函数的声明都会被提升到顶部执行,第二个函数的声明会把第一个函数的声明给覆盖掉
- JavaScript代码执行之前,需要先做变量提升。而之所以需要实现变量提升,是因为JavaScript代码在执行之前需要先编译
- 在编译阶段,变量和函数是会先被存放到变量环境中,变量的默认值会被设置为undefined;在代码执行阶段JavaScript引擎会从变量环境中去查找自定义的变量和函数--就是所谓的执行上下文
- 如果在编译阶段,存在两个相同的函数,那么最终存放在变量环境中的是最后定义的那个,这是因为后定义的会覆盖掉之前定义的
showName(); // 1
var showName = function(){
console.log("2")
}
showName(); // 2
function showName(){
console.log("1")
}
// 2
同名变量和函数的两点处理原则:
- 如果是重名的函数,JavaScript编译阶段会选择最后声明的那个
- 如果变量和函数同名,那么在编译阶段,变量的声明会被忽略
理解一下下面的代码
var showName = undefined
var showName = function(){
console.log("2")
}
showName(); // undefined报错
function showName(){
console.log("1")
}
// 编译阶段
VariableEnvironment
showName->undefined
showName->function(){...}
// 执行阶段
VariableEnvironment
showName->undefined
条件语句中声明函数的变量提升是什么样的呢?
(function(){
console.log(fn) // undefined
if(true){
console.log("hello")
function fn(){
return true
}
}
}
)
因为块级作用域中定义的变量或者函数在外部是是无法使用的,所以这里是undefined
ES规定函数不能在块级作用域中声明函数,