目录
- 例1
- 例2
- 例3
例1
- 输出:100 10 10
var a = 100;
function test() {console.log(a);//100a = 10;//全局console.log(a);//10
}
test();
console.log(a);//被修改后的全局10
- 分析:第一行代码全局的a赋值为100,先调用test()。第一个console.log(a)在块级作用域里面,在 JavaScript 里,变量的查找遵循「作用域链」——先在当前函数(局部)里找,有就用它;找不到就一路往上,最后到全局。所以这行打印找到的是全局的100。a=10,在作用链上找到全局的a修改为10,所以后面两个打印出来的都是10。
例2
- 输出:undefined 10 100
var a = 100;
function test() {
//var a;console.log(a);//undefinedvar a = 10;//变量提升到当前作用域顶部,有var局部console.log(a);//10
}
test();
console.log(a);//全局100
- 分析:第一行代码全局的a赋值为100, test块级作用域内,发现有变量的申明,先将var a提升到当前块级作用域的顶部,所以第一个console.log(a)为undefined,此时还没赋值。var a = 10将局部声明的a赋值为10,接下来console.log(a)是10当前作用域的a。最后的console.log(a)不在块级作用域内,打印的是全局的a也就是100。
例3
- 输出:0 0、f a(){} 0、1 0、1 1、21 1、里面 21、外面 1
var a = 0//全局变量
console.log(a,window.a);//0 0,全局 var 声明会挂到 window 上
if(true){//块级作用域console.log(a,window.a);//f a(){} 0a=1;//局部改为1console.log(a,window.a);//1 0function a(){}//变量提升,默认是非严格模式,严格模式需要显式的声明,执行到这行才同步全局的修改//函数的声明=创建一个函数对象+把它赋值给某个标识符,var a = function a(){}console.log(a,window.a);//a =21;//局部a=21console.log(a,window.a);//21console.log('里面',a)//21
}
console.log('外部',a)//全局
- 分析:第一行代码var a = 0 全局的a赋值为0,全局 var 声明会挂到 window 上,所以第一个console.log的值为0 0。接下来进入块级作用域,首先需要注意:函数的声明=创建一个函数对象+把它赋值给某个标识符,所以function a(){}等同于var a = function a(){}。存在函数的声明function a(){},需要提升到当前作用域的顶部。所以第二个console.log的值为f a(){} 0。接下来a=1修改的是作用链上最近的a,也就是刚刚声明的a, 所以接下来的console.log值为:1 0。来到了function a(){},这一行代码才会执行,将局部的修改同步到全局(原因是:非严格模式下浏览器会做兼容处理,执行到代码时同步全局的修改)所以接下来的console.log值为1 1。a=21修改局部的a,这时候console.log值为21 1。console.log('里面',a)的a为21。console.log('外部',a)打印的a是全局的a为1。
- 严格模式/非严格模式:严格模式的出现是为了解决早期 JS 的兼容怪癖、增强安全性、提高性能,并为 ES6+ 做好铺垫。严格模式需要明确开启:普通
<script>→ 默认非严格。<script type="module">→ 默认严格
