JS三座大山再学习(二、作用域和闭包)
作用域
JS中有两种作用域:全局作用域|局部作用域
栗子1
console.log(name); //undefined var name = '波妞'; var like = '宗介' console.log(name); //波妞 function fun(){ console.log(name); //波妞 console.log(eat) //ReferenceError: eat is not defined (function(){ console.log(like) //宗介 var eat = '肉' })() } fun();
- name定义在全局,在全局可以访问到,所以 (2) 打印能够正确打印;
- 在函数fun中,如果没有定义name属性,那么会到它的父作用域去找,所以 (3) 也能正确打印。
- 内部环境可以通过作用域链访问所有外部环境,但外部环境不能访问内部环境的任何变量和函数。类似单向透明,这就是作用域链,所以 (4) 不行而 (5) 可以。
那么问题来了,为什么第一个打印是"undefined",而不是"ReferenceError: name is not defined"。原理简单的说就是JS的变量提升
变量提升:JS在解析代码时,会将所有的声明提前到所在作用域的最前面
栗子2
console.log(name); //undefined var name = '波妞'; console.log(name); //波妞 function fun(){ console.log(name) //undefined console.log(like) //undefined var name = '大西瓜'; var like = '宗介' } fun();
相当于
var name; console.log(name); //undefined name = '波妞'; console.log(name); //波妞 function fun(){ var name; var like; console.log(name) //undefined console.log(like) //undefined name = '大西瓜'; like = '宗介' console.log(name) //大西瓜 console.log(like) //宗介 } fun();
注意:是提前到当前作用域的最前面
栗子3
printName(); //printName is not a function var printName = function(){ console.log('波妞') } printName(); //波妞
相当于
var printName; printName(); //printName is not a function printName =