涉及引用类型,作用域链的一道经典面试题

164 阅读1分钟

现在我们首先来看一道题目

var b = [1,2,3]
function fn(){
    b[3] = 4;
    b = [100]
}
fn()
console.log(b)

上面代码的输出值是多少呢?

或许大家一看这个比较简单,不就是 [100]吗

那么如果我们将代码修改一下,如下

var b = [1,2,3]
function fn(b){
    b[3] = 4;
    b = [100]
}
fn(b)
console.log(b)

现在输出应该是多少呢?

在我们分析这段代码之前大家需要了解以下几个知识点:

  1. JavaScript中数组和对象属于引用类型
  2. 作用域链的知识
  3. 参数相当于一个局部变量

现在让我们来分析下这段代码

  1. 向fn函数传入参数b相当于在fn函数内部定义了一个和全局变量b指向相同内存的局部变量b。
  2. 由于数组是引用类型,在修改局部变量b的时候,导致全局变量b发生相应改变。
  3. fn函数内部执行完 b[3] = 4 后,根据作用域链的知识,这个b应该是局部变量b,但是由于全局变量b和局部变量b指向相同的内存,修改局部变量b也会导致全局变量b改变,此时的全局变量b = [1,2,3,4]。
  4. fn函数内部执行完 b=[100] 后,局部变量b指向新的内存,全局变量b没有改变。
  5. 最后打印出的b是全局的b,故打印出的值为[1,2,3,4]
  6. 我们不妨在fn内部打印一下b,就会发现局部变量b的值为[100]