1.基本类型的直接赋值操作,原始值不会改变,一个变量只能关联一个值; 2.引用类型的直接复制,原始内存会改变。由于空间地址指向同一地址,所以也会改变。
栈内存的作用:叫做作用域 作用:1.提供JS代码自上而下执行的环境,也就是JS都是在栈内 存中执行的。 2、由于基本数据类型比较简单,他们都是直接在栈内存中 开辟一个位置,吧值直接存储进去的。
=》当栈内存被销毁,存储的那些基本值也会跟着销毁
堆内存:引用值对应的空间 作用: 1.存储引用类型值得:对象:键值对 函数:代码字符串 =>当前堆内存释放销毁,那么这个引用值彻底没了 =>堆内存的释放,当堆内存没有被任何的变量或者其他东西所占用,浏览器会在空闲的时候,自主的进行内存回收,吧所有不被占用的堆内存销毁掉(webket,谷歌浏览器) 通过设置为 xxx=null 指向空对象指针可以让原始变量销毁。
变量提升: =>当栈内存(作用域),JS代码自上而下执行之前,浏览器首先会吧所有带 var/function 关键字的进行提前声明或者定义,这种预先处理机制称之为变量提升。 ` =>变量提升阶段: 带var的只声明未定义,带function的声明和赋值都完成。
=> 变量提升只发生在当前作用域,例如开始加载页面的时候只对全局作用域进行提升,因为此时函数中存储的都是字符串而已。
=>在全局作用域下声明的函数或者变量是全局变量。在私有作用域下声明的变量是私有变量。
=>ES3/ES5语法规范中,只有全局作用域和函数执行的私有作用域(栈内存),其他大括号不会形成栈内存。
=>在全局作用域下声明的变量,相当于给window全局对象设置了一个属性。私有作用域中声明的变量与window无关。
‘age’ in obj // in 是检查对象是否存在某个值。
***变量提升 只提升当前var的变量,不提升值,比如: var a = 12; 只提升 var a ; 执行完之后再提升12.
***function提升,会提升函数和值,比如 function a(){var b =1} a() 提升, b=1也提升。
a = window.a;
函数执行形成私有作用域
var a =b =12; // var a; b = 12; a是变量提升 所以a在局部函数中是undefined;
私有作用域带var和不带var的区别 1.带var的在私有作用域变量提升阶段,都声明为私有变量,和外界没有任何的关系 2.不带var不是私有变量,会向上级作用域查找,看是否为上级的变量,不是则继续向上查找,一直找到window为止。我们爸这种查找机制叫做 作用域链, 我们在私有作用域中操作的这个非私有变量 是一直操作别人的。
带 var的提前声明,但是不会定义也就是不会赋值 带function的提前声明和定义。
浏览器中,在当前作用域下,不管条件是否成立都要进行变量提升。
if(1===2) {var a = 12;} var a; 变量提升,但是不会定义 带function的 不管条件是否成立,在老版本中提前声明和定义,新版本中只声明,但是不会定义。
谷歌 40几以上的都是新浏览器,40以下的都是老浏览器
私有作用域中: function g; 变量提升 g是私有变量
let 在当前作用域下不能声明相同名字的变量。否则会报错。
ES6中基于let/const等方式 切断了全局变量和window属性的映射机制。
let 会形成一个私有作用域,暂时性死区。
if(true) {console.log(a) let a = 13;} // a is not defined
在原有浏览器渲染机制下,基于typeof等逻辑运算符检测一个未被声明的变量,不会报错,返回undefined
在ES6中 is no defined
在私有作用域中,只有以下两种情况是私有变量 1.声明过的变量(带var/function) 2.形参也是私有变量
私有作用域特点:形参赋值,变量提升。
剩下的都不是私有的变量,都需要基于作用域链的机制向上查找。
全局作用域 第一件事情 变量提升 函数执行,形成一个私有作用域A,A的上级作用域是谁,和他在哪创建的有关系,在哪创建的,它的上级作用域就是谁。