js作用域详解

在es5中,js是没有块级作用域的,只有函数作用域,而且函数作用域是链式的,内层函数可以访问到外层函数中的变量,外层函数是访问不到内层函数中的变量的,在es6中,新增了let和const命令,使得js拥有了块级作用域,不再需要使用函数来模拟块级作用域,下面来通过几个例子来分析一下js中的作用域问题。

一.函数作用域分析 

1.函数的链式作用域分析

function add() {
color = "aa";
}
console.log(color);

在上面这段代码中,color能否被打印出?答案是不能的,因为函数未被执行,color未进入内存中,必须在打印color之前调用这个函数,color才可以被打印出。

function add() {
var color = "aa";
}

add();
console.log(color);

在这段代码中,color仍然无法被打印,因为var定义了一个局部变量,在函数执行后,color就被销毁。

function add() {
color = "aa";
}

add();
console.log(color);

这段代码中,color可以被正确打印出,但并不推荐这种不声明变量直接赋值的写法,这在严格模式中会报错。

但我们在很多时候需要在外层函数中访问内层函数中的变量,这时候我们就用到了闭包,来看一个最简单的例子。

function A(){

    a=123;
    function B(){

       return a;
    }
    return B;
}
A();// 123

看似和直接执行A函数效果一样,但其实我们是使用了A函数中嵌套的B函数来获取到了a,这个函数并没有实际作用,但当将A作为构造函数,B为A函数的对象方法时,a就成为了私有属性。

二. 块级作用域分析

1.es5中无块级作用域带来的影响

var a = [ ];
for (var i = 0; i < 10; i++) {
  a[i] = function () {
    console.log(i);
  };
}
a[1]();

首先我们来看上面的例子,运行这段代码的结果是10,有很多人会问为什么是10呢,这就是没有块级作用域所带来的影响,调用a[1]时,会运行console.log(i),这其中的i是哪个i呢?是当初循环定义中的那个i吗?不是的,因为没有块级作用域导致内存泄漏,这里i的值是for循环结束后的值,也就是10,不管运行a[]中的哪一个,结果都是10.

为了避免产生内存泄漏,在es5中我们常用函数来模拟块级作用域,来看下面这个例子。

var gg=[];
for (var x = 0; x < 10; x++) {
   gg[x] = function (num) {
    return function(){
      console.log(num);
  };
  }(x);
}

gg[1]();

在这个例子中,我们使用立即执行函数来模拟块级作用域来让函数能够正常运行。

2.在es6中增加了let和const命令,使得js拥有了块级作用域,上面示例中的代码可以像下面这样写。

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

猜你喜欢

转载自blog.csdn.net/qq_41635167/article/details/81876352
今日推荐