转载声明:文章来源:https://blog.csdn.net/weixin_44772409/article/details/106639007
关于数据值的操作机制
栈内存:作用域
1.提供一个存放供js代码自上而下执行的环境(代码都是在栈中执行的),
2.由于基本数据源类型值都比较简单,他们都是直接在栈内存中开辟一个位置,把值直接存进去
ps:当栈内存被销毁,存储的那些基本值也就被销毁了。
堆内存:引用值对应的空间
1.存储引用类型值(对象:键值对 函数: 代码字符串)
ps:当前堆内存释放销毁,那么这个引用值彻底没了
堆内存的释放:当堆内存没有被任何变量或任何其他东西所占用,浏览器会在空闲的时候,自主的进行回收,把所有不占用堆得内存销毁掉(谷歌浏览器,IE浏览器采用计数的功能,但有时候计数会出现混乱,也就导致了内存泄漏问题)。
XXX=null 通过空对象指针null可以让原始变量(或其他东西)谁都不指向,从而原来被占用的堆内存就不再被占用,浏览器就会销毁它。
变量提升机制
1.变量提升
当栈内存(作用域)形成的,js代码自上而下执行之前,浏览器首先会把带有 “var”、"function"关键字的进行提前“声明”或“定义“,这种预先处理的机制就是变量提升。
声明(declare):var a ; (声明的时候 默认返回值是undefined)
定义(defined):a=12 (定义也可以简单理解为赋值)
变量提升阶段:
带“var”关键字只声明不定义;
带"function"关键字赋值和定义都完成了;
注意:变量提升只发生在当前作用域(eg: 开始加载页面的时候只对全局作用域下的进行变量提升,因此函数中存储的只是代码字符串而已)
从广义上说,在全局作用域下声明的变量或函数是”全局变量“,同理,在私有作用域下声明的变量时”私有变量“,【带有 “var”、"function"关键字的才是声明】,不带var声明的 变量就得一层一层向上级作用域查找,直到查找到全局无论是否找到都得停止
私有作用域形成之后,代码也并不是立即执行,带有形参的函数要先进行形参的赋值,再进行变量提升,在函数中遇到的大括号(例如for循环、if语句)不会形成栈内存,因为在ES3/ES5语法规范中明确规定了只有全局作用域和函数执行的私有作用域(栈内存),其他大括号不会形成栈内存。
值得注意的一点是,由于之前声明时函数已经被声明并且定义,当代码在自上而下执行时浏览器会直接跳过那一段被声明切赋值的函数。
2.条件判断下的变量提升
在当前作用域下,不管条件是否成立都要进行变量提升
带“var”的还是之声明
带“function”的在老版本浏览器的渲染机制下,既会声明也会定义,但是为了迎合ES6中的块级作用域,新版浏览器对于函数(在条件判断中的函数),不管条件是否成立,都只是先声明并不会定义。
/*
变量提升: function fn;
*/
console.log(fn) //undefined
if(1==1){
/*
变量提升:(fn)===> 函数体内容
*/
console.log(fn); //函数本身 当条件成立时,进入到判断体中,就会在当前的if语句形成的块级作用域中(ES6语法),在代码执行前,进行与类似变量提升的操作一样吗,将带有function关键字的函数进行声明(由于之前声明过了,便不再重复声明)和赋值(这里会进行赋值),也就是if语句中的代码执行前,fn函数已经被赋值了。
function fn(){
console.log("ok");
}
}
console.log(fn) //函数本身
3.变量提升——重名问题的处理
由于变量在作用域中不允许重名,所以对于在同一个作用域中的变量会采取覆盖的操作。
举例:
/*
变量提升:fn:===>(1)
===>(2)
===>(3)
===>(4)
*/
fn();//4
function fn(){ console.log(1)};
fn();//4
function fn(){ console.log(2)};
fn();//4
var fn=100;
fn();//报错 fn不是一个函数 代码不再向下执行
//由于带"var"关键字的在变量提升阶段只把声明处理了,并没有赋值,所以在代码执行到fn=100时,函数已经不再是一个函数,而是一个普通的变量值
function fn(){ console.log(3)};
fn();
function fn(){ console.log(4)};
fn();
好文,喜欢看,比书上的好
有没有蜕变测试或者ai测试的教程