ES6中块级作用域

来源:互联网 发布:Unieuro.it 编辑:程序博客网 时间:2024/06/05 16:47
var name="World";(function(){  if(typeof name==='undefined'){   var name='Jack';console.log('Goodbye'+name);}else{  console.log('hello '+name);}})() 

函数作用域内var变量声明提升: 变量的声明会提升到当前作用域的顶部
等价于:

var name = "World";(function () {  var name //声明提升  if (typeof name === 'undefined') {    name = 'Jack';    console.log('Goodbye' + name);  } else {    console.log('hello ' + name);  }})()
var name = "World";(function () {  if (typeof name === 'undefined') {    name = 'Jack';//声明全局变量    console.log('Goodbye' + name);  } else {    console.log('hello ' + name);  }})()输出:hello World

注意:
ES5中只有全局作用域函数作用域。函数作用域的同名变量覆盖了全局作用域该变量的值。

为什么需要块级作用域?

ES5中只有全局作用域函数作用域,带来了很多不合理的场景。
场景一:内部的变量可能会覆盖外层变量

var temp = new Date();function f() {  console.log(temp);  if(false){//即使为false    var temp = "hello world";  }}f();//输出 undefined

原因是变量提升导致内部的变量覆盖了外层的temp变量,ES5中,不管会不会进入if代码块,变量都会提升到当前作用域顶部。
场景二:用来计数的循环变量泄漏为全局变量

var s= 'hello';for (var i = 0; i < s.length; i++) {    console.log(s[i]);}console.log(i);//5

上述代码,变量i只是用来控制循环,但在循环结束后,它并没有消失,而是泄漏成了全局变量。

(function () {  var name; //声明提升})()console.log(name);//ReferenceError: name is not defined

立即执行函数的作用域是可以访问全局的, 全局的无法访问立即执行函数

立即执行函数内部可以看作是一个块作用域, 与外层不是同一个作用域了, 查找变量是也是会一层一层作用域往上找, 先在当前的作用域中找, 找不到才往上一个作用域找。 然后 var 声明是会提升到当前作用域最顶层, 也就是立即执行函数内部的最顶层, 所以执行if时 是会找到var name 这句的。 (如果改成const let 这种是不会提升变量的, 那if就找不到 会返回hello world )
ES6中的块级作用域,使得广泛使用的立即执行匿名函数不再必要了。

另外ES6也规定,函数本身的作用域在其所在的块级作用域之内

function f() {  console.log('I am outside!');}(function () {   if(false){     function f() {       console.log('I am inside!');     }   }  f();}())

在ES5中运行,得到I am inside!,在ES6中运行,得到I am outside!。这是因为ES5中存在函数提升,不管会不会进入if代码块函数声明都会提升到当前作用域的顶部而得到执行;而ES6支持块级作用域,不管会不会进入if代码块其内部声明的函数皆不会影响到作用域的外部

例子

const a = [];for (let i = 0; i < 10; i++) {  a[i] = function () {    console.log(i);  };}a[1]()//输出 1

知识点:变量i是let声明的,当前i只在本轮循环有效。所以每一次循环的i其实都是一个新的变量。

注意:ES6不存在变量提升