欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

JS作用域和内存基本分析

程序员文章站 2022-03-02 13:50:55
...

1. JS作用域

1.1 如何查找当前作用域的上级作用域

  • 看当前函数是在哪个作用域下定义的,那么它的上级作用域就是谁
  • 和函数在哪执行没有任何关系
  • 示例代码
var num = 12;
function fn() {
    var num = 120;
    return function() {
        console.log(num);
    }
}  
var f = fn();
f();//输出120
(function(){
    var num = 200;
    f()//同样输出120
})()
//分析如下
//f = fn() 假设fn执行形成了私有作用域A  ===> f = function() { console.log(num) }(匿名函数表达式)
//f() ---相当于执行匿名函数 function() {console.log(num)} 输出num  形成私有作用域B 
//由于B中没有num 所以往上级作用域A中查找num 刚好A中有var num = 120; 
//所以无论f() 在哪执行 都不受影响 输出 都是A中作用域num的值 120
复制代码
  • 附示意图

2. JS内存释放

2.1 堆内存

  • 对象数据类型和函数数据类型在定义的时候首先都会开辟一块堆内存,堆内存有一个引用的地址
  • 如果外边的变量知道了这个地址,我们就说这个内存被占用了,就不能销毁了
  • 我们想要让堆内存释放/销毁,只需要把所有引用它的变量赋值为null即可
  • 如果当前的堆内存没有被任何变量占用,那么浏览器就会在空闲的时候把它销毁 (不同的浏览器销毁方式不同)
var obj1 = { name:"dashuaige", age:18 };
var obj2 = obj1;
//如果要释放这块内存 obj2 = obj1 = null;
复制代码
  • 示意图

2.2 栈内存(全局/私有作用域)

  • 私有作用域:只有函数执行会产生私有作用域
  • 全局作用域:window(只有当页面关闭的时候,全局作用域才会销毁)

2.2 作用域销毁问题

  • 一般情况下,函数执行会形成一个新的私有作用域,当私有作用域中的代码执行完成后, 我们当前的作用域都会进行主动的释放和销毁
  • 函数执行完 ---> 作用域销毁
  • 下面重点介绍作用域不销毁的情况 a、函数执行返回了一个引用数据类型的值,并且在函数的外边被一个其他的变量给接收了, 这种情况下一般形成的私有作用域都不会销毁
function fn() {
    var num = 100;
    return function() {};//返回引用类型的数据(堆内存)
}
var f = fn();
//fn执行形成的这个私有作用域就不会再销毁了
复制代码

上述a的文字解释 函数fn执行 形成了私有作用域A 假设返回的function() {} ---->地址为xxxfff111 f = xxxfff111 相当于A作用域下的堆内存 xxxfff111 被外部的变量f给占用了 那么xxxfff111这个堆内存不能释放 对应A这个私有作用域也不能销毁

b、在一个私有作用域下给Dom元素的事件绑定方法,一般情况下我们的私有作用域都不销毁

var oDiv = document.getElementById("#div1");
(function() {
    oDiv.onclick = function() {
        console.log("you are so handsome")
    }
})()
//当前这个自执行函数的私有作用域不销毁
复制代码
  • 附示意图

c、下述情况属于"不立即销毁" --->fn返回的函数没有被其他东西占用,但是还需要执行一次呢, 所以暂时不销毁,当返回的函数执行完成后,浏览器会在空闲的时候把它销毁

function fn() {
    var num = 100;
    return function() {
        console.log("1111");
    }
}
fn()();
//首先执行fn 返回一个小函数的内存地址,然后紧接着让返回的小函数再执行
复制代码

2.3 作用域经典练习题

function fn() {
    var i = 10;
    return function(n) {
        console.log(n + (++i))//i++ 和 ++i 都是自身累加1 i++ 先拿i的值进行计算,运算完成再加1 
        //++i 先本身累加1 然后拿累加完成的结果去运算

    }
}
var f = fn();
f(10);//输出21
f(20);//输出32
fn()(10);//输出21
fn()(20)//输出 31
复制代码
  • 示意图太大 这个文章放不了 请看上一个文章(作用域经典练习题)

  • 动力: 这是我的学习笔记,您能从中得到收获和进步,是我分享的动力,帮助别人,自己也会更快乐

  • 期望: 不喜勿喷,谢谢合作!如果涉及版权请及时联系我,马上删除!