堆栈内存的销毁 闭包 this

1,249 阅读3分钟

堆内存的销毁

堆内存的销毁:
        引用数据类型存放的地点
        谷歌浏览器,是定时清除,每隔一段时间 就会 通篇清除 销毁一次,是把js中没有被用到的地址全部销毁
        火狐浏览器,用的是计数清除,根据当前地址的引用个数来决定这个地址是否要被销毁 引用个数是0 就会被销毁
栈内存的销毁:
        提供代码运行环境,存放值类型
        全局作用域的销毁:当页面关闭的时候才会销毁;
        私有作用域的销毁:只要函数的返回值是一个引用数据类型,那么这个作用域就不会被销毁
栈溢出  内存泄露 :栈内存不够用了 
var a = [1,2,3,4]
a = 12;
function f () {
    var a = 100;
    btn.onclick = function () {
        console.log(a);
    }   //这个作用域也不会被销毁,不然 onclick 里面的a使用不了,所以关键是看有没有东西占用函数里的东西
}
f (); 

闭包

闭包(closer)就是一个变量的保护机制;
        闭包首先是一个不销毁的作用域,用来保护变量,和存储值
        利用闭包 我们可以实现模块化开发;
    闭包的缺点:用多了容易引起内存泄漏

this

箭头函数中,没有this和arguments; 箭头函数里把this和arguments当作普通变量去对待的
                箭头函数中的this 是指向了上级作用域 的this

    this 就是函数的执行主体

    事件绑定中的this 就是当前绑定的元素

    自执行函数 中的 this 是window

    定时器中的this 也是window

    this 的指向是谁,我们可以通过看点的方式 来确定:函数执行点 前 是谁 this就是谁,没 点 就是window
var btns = document.querySelectorAll('button');
[...btns].forEach(item => {
    item.onclick = function (){
        console.log(this)
    }
});


(function(){
    console.log(1,this)
})()
~function(){
    console.log(2,this)
}()  //这也是函数自执行
~function(){
    console.log(3,this)
}() //这也是函数自执行

var obj = {
    age:100,
    f(){
        console.log(this)
    },
    f2:function (){

    },
    f3:() =>{
        console.log(this)
    }
};
//obj.f === fn === ary[3]
obj.f()  //这个this 是obj.age
var fn = obj.f;
fn();  //前面没点  window.age
var ary = [1,2,3,fn];
ary[3]();  // 前面没点,但是数组的下标这里只能用中括号,数组就是一个特殊的对象 这里中括号就是个.  所以这里的this是ary
obj.f3();//  这是箭头函数 this是普通变量,向上级查找this 后来是window

function fn2 () {
    return ()=>{
        console.log(arguments)
    }
}
fn2(1,2,3,4,5)()  //这里 arguments被当作普通变量 因为这个箭头函数里没有arguments所以向上级作用域中找

setTimeout(function () {
    console.log(this) //window
},2000)

var num = 1;
var obj = {
    num:10,
    fn:(function(){
        this.num *= 3;
        return function () {
            num += 2;
            this.num++;
        }
    })()
}
var f = obj.fn;  //  window的num 变成3
f();
obj.fn();
console.log(num,obj.num);

var name = '珠峰';
var age = 9;
age = (function (name,age) {

})()

var a = {
    x:1
}
var b = a;
b.y = a = {
    qqq:123
}
console.log(a.x,b.x);  // undefined  1 

各行变色中循环 var let

<body>
<button>100</button>
<button>200</button>
<button>300</button>
<button>400</button>
<button>500</button>
</body>
<script>
var btns = document.querySelectorAll('button');
for (let i = 0; i < btns.length; i++) {
    btns[i].onclick = function () {
        alert(`我是第${i+1}个`)
    }
}
//为什么这个循环里let 好使,var 不好使 因为let 能识别块级作用域,

//因为就是为了拿到自己的i,而不是全局的i,所以我们可以用闭包存一下自己的i

for ( var i = 0; i < btns.length; i++) {
    btns[i].onclick = (function (){
        return function (){
            alert(`我是第${i+1}个`)
        }
    })(i)
}

//我们还可以用forEach
[...btns].forEach ((item,index) => {
    item.onclick = function () {
        alert(`我是第${index+1}个`)
    }
})
//首先用[...btns]把btns这个类数组转变为数组,forEach这个回调函数也有item的个数的个数,而且不会被销毁,因为被引用 就是有5个执行域
</script>