3、作用域与内存
一、js中内存的分类:
栈内存:用来提供一个供js代码执行的环境--如:作用域(全局作用域/私有作用域)-----预解释就在栈内存里面
堆内存:用来存储引用数据类型的值-->如:对象存储的是属性名和属性值,函数存储的是代码字符串。
二、全局变量与私有变量:
全局变量:在全局作用域下声明的变量(预解释的时候)是全局变量
私有变量:在私有作用域下声明的变量 和 函数的形参 都是私有变量
在私有作用域中,代码执行的时候遇到一个变量:
首先要确定是否为私有变量,如果是私有变量(1、看是不是形参,2、有没有var过),则和外面没有任何关系,
如果不是私有变量,则网当前作用域的上一级作用域查找,如果上级也没有继续查找,一直找到window为止(作用域链)。
三、函数执行:
函数定义三阶段:
1)开辟一个空间(堆内存)生成一个地址。
2)把函数体转为字符串存到空间。
3)把空间地址复制给函数名。
当函数执行的时候(直接目的:让函数体中代码执行),首先会形成一个新的私有作用域,然后:
1)如果有形参先给形参赋值
2)进行私有域中的预解释
3)私有域中的代码由上到下执行
4)字符串转为代码-从上到下执行
函数执行形成的私有作用域保护了里面 私有变量 不受外面干扰(但可以对全局变量进行修改)---"闭包" 一种机制。
四、查找上级作用域:
看当前函数是在哪个作用域下定义的,那么他的上级作用域就是谁。和函数在哪执行没有任何关系。
五、内存释放:
堆内存:引用数据类型(对象 函数)在定义的时候首先会开辟一个堆内存,并有一个引用地址,如果外面的变量等知道了这个地址,
我们就说这个内存被占用了,就不能销毁了。 我们想让堆内存释放/销毁,只需要把所有引用他的变量值赋值为null(null为空指针)即可,
如果当前的堆内存没有任何东西被占用,那么浏览器会在空闲的时候把它销毁。。。
栈内存:全局作用域--只有当页面关闭的时候,全局作用域才会销毁。
私有作用域--只有当函数执行的时候才会产生私有作用域,
一般情况下,函数执行形成一个新的私有作用域,当私有作用域
中的代码执行完成后,都会主动的进行释放和销毁。(浏览器对内存的回收与释放机制)
特殊情况:当前作用域中的部分内存被作用域外的东西占用了,那么当前作用域就不能被销毁了
a、函数fn执行返回了一个引用数据类型的值,并且在函数的外面被其他东西接收占用,这种情况函数执行产生的私有作用域不销毁。
b、不立即销毁
function fn(){ var i=10; return function(n){ console.log(n+(++i)) } } var f=fn(); f(15); f(20);//不销毁 函数中return的返回值被变量f占据 之后后面小函数执行完毕销毁 fn()(15);//不立即销毁 函数中return的返回值被变量f临时占据,(15)执行完毕后都销毁了。 fn()(20); fn()(30); f(30);
六、this指向:
1.元素事件被触发,this指向该元素
2.当函数被调用的时候,点.前面是谁 this就是谁
3.自执行函数的this都是window。