堆内存的销毁
堆内存的销毁:
引用数据类型存放的地点
谷歌浏览器,是定时清除,每隔一段时间 就会 通篇清除 销毁一次,是把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>