js基础(五) 内存释放和作用域销毁

7/15/2017 javaScript面试

# 知识点一 堆内存释放

  • 对象数据类型或函数数据类型在定义的时候首先都会开辟一个堆内存,堆内存有一个引用地址,如果外面有变量等知道(引用)这个内存被占用了,就不能销毁了
var obj1 = {name: '张三'}
var obj2 = obj1
1
2
  • 想让堆内存释放/销毁,只要把所有引用它的变量值赋值为 null 即可,如果当前的堆内存没有任何东西被占用了,那么浏览器会在空闲的时候把它销毁
var obj1 = null
var obj2 = null
1
2

# 知识点二 栈内存释放

  • 全局作用域
    • 只有当页面关闭的时候全局作用域才会销毁
  • 私有作用域

    • 只有函数执行会产生私有的作用域

    • 立即销毁:一般情况下,函数执行会形成一个新的私有的作用域,当私有作用域中的代码执行完成后,我们当前作用域都会主动销毁

    • 不销毁:当前私有作用域中的部分内存被作用域以外的东西占用了,那么当前的这个作用域就不能销毁了,如案例中的作用域A

      • 函数执行返回了一个引用数据类型的值,并且在函数的外面被一个其他东西给接受了,这种情况下一般形成的私有作用域都不会被销毁,例如
function fn() {
  var num = 100
  return function() {}
}
var f = fn() // fn执行形成的这个私有作用域就不能再销毁了
1
2
3
4
5
      • 在一个私有的作用域中给DOM元素的事件绑定方法,一般情况下我们的私有作用域都不销毁
var oDiv = document.getElementById('div1')
~function() {
  oDiv.onclick = function() {}
}() // 当前自执行函数形成的这个私有作用域也不能销毁
1
2
3
4

image.png

  • 不立即销毁下述情况属于不立即销毁,fn 返回的函数没有被其它的东西占用,但是还需要执行一次,所以暂时不销毁,返回的值执行完成后,浏览器会在空闲的时候把它销毁了
function fn() {
  var num = 100
  return function() {}
}
fn()() // 首先执行fn,返回一个函数对应的内存地址,然后紧接着让返回的函数在执行
1
2
3
4
5

# 案例分析一

var num = 12
function fn() {
  var num = 120
  return function() {
    console.log(num) // --> 120
  }
}
var f = fn()

f()

~function() {
  var num = 1200
  f() // --> 120 
}()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

image.png

# 案例分析二

function fn() {
  var i = 10
  return function(n) {
    console.log(n + (++i))
  }
}
var f = fn()
f(10) // 21
f(20) // 32
fn()(10) // 21
fn()(20) // 31
1
2
3
4
5
6
7
8
9
10
11

image.png

# 参考

闭包(Closures) (opens new window)