JS栈内存和堆内存详解
上章节详细讲解了JavaScript底层的运行机制,这章节就好好来讨论下js代码运行开辟出的 堆和栈
,以及变量之间复制,诸如 var a = 10; a = b;
这类代码的原理
栈内存
:拥有作用域,代码执行空间,存储基本值和变量
- 提供一个供 JavaScript 代码自上而下执行的 window 全局栈内存(代码都是在栈中执行的)
- 基本数据类型会直接在栈内存中存放的,引用数据类型会开辟一个堆内存类存放,并且用指针指向其地址
堆内存
:引用值存储空间
-
存储引用类型值的(对象:键值对形式,函数:字符串形式)
=> 当前堆内存如果释放,那么这个引用空间就会彻底销毁,包括里面所有值
=> 堆内存的释放:如果还有变量指向该内存,就不会释放,只要还有一个变量指向,就不会释放(类python)
=> 变量 = null ,也是一个不错的内存释放方法,一个变量如果指向 null,也就是指向空对象指针,原有被指向的对象就是少一层指向
复制变量值的区别
基本类型值的复制
下面这段代码,能把基本类型变量的复制解释清楚
var a = 10;
var b = a;
// 基本类型复制
复杂数据类型的复制
下面这段代码,能把应用类型变量的复制解释清楚
var m = {name: 'xyb'};
var n = m;
// 基本类型复制
复制变量值练习
这个案例能很好体现 基本类型的复制 和
引用类型的复制
-
已知下面代码可以修改BOX元素的样式
box.style.color = 'green';
-
那么下面的写法是否可以修改元素的样式,如果不可以是为什么?
//第一种方案 let AA = box.style; AA.color = 'red'; //第二种方案 let BB = box.style.color; BB = 'red'; //=>哪种方式可以实现,不能实现是因为啥?
第一种可以:对指针内栈内存里的值进行操作,JS会基于DOM映射机制把页面元素进行重新渲染
第二种不可以:其只是把box.style.color的值复制了一份新的而已,并且只改变了本身BB变量的指向
内存地址小练习
let n = [10, 20];
let m = n;
let x = m;
m[0] = 100;
// m ,n, x [100, 20]
n = [30, 40];
// n, [30, 40] m, x [100, 20]
n[0] = 200;
// n, [200, 40] m, x [100, 20]
x[0] = 200;
// n, [200, 40] m, x [200, 20]
m = [50, 60];
// n [200, 40] x [200, 20] m [50, 60]
m = x;
// n [200, 40] x m [200, 20]
m[1] = 300;
// n [200, 40] x m [200, 300]
n[2] = 400;
// n [200, 40, 400] x m [200, 300]
console.log('n: ' + n);
console.log('m: ' + m);
console.log('x: ' + x);
大公司面试题
-
阿里
let a = { n: 1 }; let b = a; a.x = a = { n: 2 }; console.log(a.x); console.log(b);
-
腾讯
var a = 'abc' + 123 + 456; var b = '456' - '123'; var c = 100 + true + 21.2 + null + undefined + "Tencent" + [] + null + 9 + false; console.log(a, b, c); // a = 'abc123456'; // b = 333; // c = 'NaNTencentnull9false'
-
腾讯
var str = 'abc123'; var num = parseInt(str); if (num == NaN) { alert(NaN); } else if (num == 123) { alert(123); } else if (typeof num == 'number') { alert('number'); } else { alert('str'); } // 弹出 Number
-
腾讯
var a = 0; var b = a; b++; alert(a) var o = {}; o.a = 0; var b = o; b.a = 10; alert(o.a)
-
输出 ‘1’ 的值
alert(1) console.log(parseInt(1.3)) console.log(1) console.log(isNaN(1)) console.log(parseInt("1")) // 1 2 3 5
-
输出 ‘undefined’ 的值
alert(1) typeof undefined parseInt(undefined) isNaN(undefined) // 2
-
输出 true 的值
isNaN(null) isNaN(parseInt(null)) Number(null) parseFloat(null) // 2
-
输出下面的结果
parseInt("") // NaN Number("") // 0 isNaN("") // 0 isNaN(Number("")) parseInt(null) // NaN parseInt(String(null)) Number(null) // 0 isNaN(null) // false isNaN(Number(null)) parseInt("12px") // 12 Number("12px") // NaN isNaN("12px") // true
-
输出下面的结果
if (isNaN(NaN) == "") { console.log("哈哈") } else { console.log("呵呵") // 输出 呵呵 }
-
输出下面的结果
let x = [1, 2, 3]; let y = x; let z = [4, 5, 6]; y[0] = 10; y = z; z[1] = 20; x[2] = z = 30; console.log(x, y, z); // x = [10, 2, 30] // y = [4, 20, 6] // z = 30