js中的作用域和作用域链

 

作用域
1. 全局作用域
2. 函数作用域
这里扯出来下js的函数声明和变量声明提升,直接来两段代码

if (!a in window) {
   var a = 1;
}
console.log(a) //undefined

嗯,为什么呢?因为var声明的变量会变量声明提升,所以相当于执行if判断的时候a变量已经声明过了,而此时a是一个全局变量既是window对象的一个属性,所以这里压根没有进if判断,所以这里打印出来的是undefined
再来一段坑坑的代码

(function (){
  var a = b = 10;
})()
console.log(b) // b是10
console.log(a) // a是局部变量所以在这里打印a的时候会报错

在函数中var a = b = 10,b暴露为全局变量,因为赋值是从右往左进行的,也就是说这一行先执行b=1,这时候b就是全局变量了,没有被var过。然后是var a = b;a被声明了,是局部变量。你赋值给a,b=1,是不存在的,var a=b=1,就可以等同于,b=1;var a=b;

那么下面这里的问题也很容易知道答案喽

var a;
var b;
(function () {
  console.log(a) // undefined
  console.log(b) //10
  var a = b = 10;
  console.log(a); // 10
  console.log(b); // 10
})();
console.log(a) // undefined
console.log(b) // 10

作用域链是怎么回事呢

1. 执行环境和作用域 (函数第一次调用的时候会创建作用域链和执行环境,并把作用域链赋值给一个内部属性[scope]),然后使用this、arguments和其他命名参数来初始化函数的活动对象。但在作用域链中,外部函数的活动对象始终处于第二位,外部函数的外部函数始终处于第三位...直至作用域链的终点全局执行环境。
2. 活动对象
3. 变量对象(每个执行环境都会有一个变量对象)

先来个函数吧!!!

var a = 10, b = 20;
function sum (a, b) {
  return a + b;
}
var result = sum(a, b)

// 在sum函数被调用的时候,会创建它的作用域和执行环境,然后,使用arguments和其他命名参数初始化其活动参数。在作用域链中,它的外部函数处于第二位,外部函数的外部函数处于第三位......,直到作用域链的终点全局执行环境

一般,在函数执行完毕后,局部活动对象就会销毁,内存中仅仅保存全局作用域(全局执行环境的变量对象)。

 闭包中的作用域链又是怎么回事呢???

在另一个函数内部定义的函数会将包含函数的活动对象添加到它的作用域链中。外部函数执行完后,虽然作用域链会销毁,但是由于内部函数仍然在引用这个活动对象,外部函数的活动对象不会销毁,一直保存到内存中,直到内部函数被销毁后,外部函数的活动对象才会被销毁。

闭包会携带包含他的函数的作用域链,所以比其他函数占用更多的内存。过度使用闭包会导致内存使用过多。

 

posted @ 2017-09-11 19:46  RunningAndRunning  阅读(185)  评论(0编辑  收藏  举报