1.JS底层运行机制之堆(Heap)栈(Stack)内存
相关理论知识
- ECStack(Execution context Stack) 执行环境栈: —— 内存中分出来用于执行js代码的空间
- EC(Execution context): —— 执行上下文, 为了区分全局和函数执行所处的不同范围(词法作用域),又可以分为全局执行上下文EC(G)和函数执行私有上下文EC(FUNC)
- VO(Varilbale Object)和AO(Active Object): —— 在每一个上下文代码执行的时候,都可能会创建变量 , 全局变量对象VO(Varilbale Object) 和 私有变量对象AO (Active Object)
- GO(global object): 内置、全局对象,——浏览器把所有供后期需要供JS调取使用的属性和方法都放在GO对象中,如setInterval、eval、JSON并且创建一个window对象指向它,使用的时候可以省略window,如window.console.log=> console.log
let a = 12; let b = 13; function func(){ let a = 1; let b = 3; } console.log( a,b ) // 12 ,13 // 由上图我们可以得知函数中的a、b变量存到了AO(FUNC)中,函数外的a、b存到了VO中,所以函数取到的应该是VO中的12,13
代码执行阶段
- 创建变量并赋值的过程【3步】 1、先创建值 基本类型的值直接存储到栈内存中 引用数据类型需要开辟一个堆内存, 把堆内存地址存放到栈中供变量调用 2、创建变量,存储在变量对象中 3、关联,让变量和值进行关联(指针指向的过程)
- 对象中属性名的类型 【说法一,属性名类型只能是字符串或者Symbol】 【说法二,属性名类型可以是任何基本类型值,处理中可以和字符串互通】 但是属性名绝对不能是引用数据类型,如果设置为引用数据类型,最后也是转换为字符串来处理的, 属性名应该是一个值
for(let key in obj){} // For In 遍历中获取的属性名都会变成字符串,并且不会迭代 到属性为Symbol类型的属性
var a ={} , b ="0" , c =0; a[b] = "蓝天" a[c] ="白云" console.log(a[b]) // 白云 var a ={} , b = Symbol("1") , c =Symbol("1") ; a[b] = "蓝天" a[c] ="白云" console.log(a[b]) // 蓝天 var a ={} , b = { n:'1' } , c = { m:'2' } ; a[b] = "蓝天" a[c] ="白云" // a['[object Object]'] console.log(a[b]) // 白云 // 连等赋值 let a = 12, b = 13; => let a =12; let b =12; let a = b = 12; // 默认从右到左 // 1、创建一个值12 // 2、b = 12; // 3、let a = 12; [mdn 运算符优先级](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/Operator_Precedence) a.x = a ={}; a = a.x = {}; 因为a.x的优先级是很大的,不管怎么调换位置,都是先处理a.x = {} var a = { n : 1 } var b = a; a.x = a = { n : 2 } console.log(a.x) // undefined console.log(b) // { n:1 , x: {n:2} } // 解析: 1、先创建值: 引用类型,开辟堆空间存{n:1}, 引用为16进制的地址如AAFFCC
思考题
var x = [12,23]; function fn(y) { y[0] = 100; y = [100]; y[1] = 200; console.log(y) } fn(x); console.log(x)
写在最后
欢迎访问我的博客rockshang.com