Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JavaScript 作用域与闭包 #40

Closed
PolluxLee opened this issue Jun 8, 2018 · 0 comments
Closed

JavaScript 作用域与闭包 #40

PolluxLee opened this issue Jun 8, 2018 · 0 comments

Comments

@PolluxLee
Copy link
Owner

PolluxLee commented Jun 8, 2018

# 作用域链

当代码在一个环境中执行时,会创建变量对象的一个作用域链。作用域链的用途,是保证对执行环境有权访问的所有变量和函数的有序访问

var color = "blue";
function changeColor() {
  var anotherColor = "red";
  function swapColors() {
    var tempColor = anotherColor;
    anotherColor = color;
    color = tempColor;
   //  这里可以访问 color、anotherColor 和 tempColor
  }
  //  这里可以访问 color 和 anotherColor,但不能访问 tempColor
  swapColors();
}
//  这里可以访问 color
changeColor();

以上代码有 3 个执行环境:

  1. 全局环境
  2. changeColor() 的局部环境
  3. swapColors() 的局部环境
window
  |__ color
  |__ changeColor()
       |__ anotherColor()
       |__ swapColors()
            |__ tempColor

局部环境会先在自己的变量对象中搜索变量和函数名,如果搜索不到则沿着作用域链往上搜索

# 闭包

闭包 = 函数 + 函数能够访问的自由变量(不是函数的形参或局部变量)

var lang = "JavaScript";
function makeFunc() {
    var name = "Mozilla";
    function displayStr() {
        console.log(lang, name);
    }
    return displayStr;
}

var myFunc = makeFunc();
myFunc();  //  JavaScript Mozilla

闭包特性

1.函数嵌套函数
2.函数内部可以引用外部的参数和变量
3.参数和变量不会被垃圾回收机制回收

优缺点

优点:有权访问另一个函数作用域里的变量,可避免全局变量的污染,可封装私有数据
缺点:常驻内存,会增大内存使用量,使用不当很容易造成内存泄露

内存泄漏

由于 IE9 之前的版本对 JScript 对象和 COM 对象使用不同的垃圾收集例程,因此闭包在 IE 的这些版本中会导致一些特殊的问题。

如果闭包的作用域链中保存着一个 HTML 元素,那么就意味着该元素无法被销毁

function assignHandler () {
  var element = document.getElementById("someElement");
  element.onclick = function () {
    alert(element.id);
  };
}

由于匿名函数保存一个对 assignHandler() 的活动对象的引用,因此就导致无法减少 element 的引用数。只要匿名函数存在,element 的引用数至少也是 1,因此它所占用的内存就永远不会被回收。所以下面的修改,用将 element.id 用副本暂存,最后把 element 引用指向 null

function assignHandler () {
  var element = document.getElementById("someElement");
  var id = element.id;
  element.onclick = function () {
    alert(element.id);
  };
  element = null;
}

# 参考

JavaScript 高级程序设计

https://segmentfault.com/a/1190000000652891#articleHeader0

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Memory_Management

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant