栈和堆
- 栈自动分配内存空间,系统自动释放,里面存放的是基本类型的值和引用类型的地址;
- 堆动态分配的内存,大小不定,也不会自动释放,里面存放引用类型的值;
栈内存
又叫作用域,提供一个 js 代码自上而下执行的环境(代码都是在栈中执行的);
由于基本数据类型值比较简单,直接在栈内存中开辟一个位置,把值直接存起来;
注意:当栈内存被销毁,存储的基本值也被销毁;
堆内存
引用值对应的空间,存储引用类型值的方式:
- 对象: 键值对;
- 函数: 代码字符串;
注意: 当堆内存消失, 那么这个引用值也消失;
执行上下文
函数执行上下文
:一个函数运行之前,创建的一块内存空间,空间中包含有该函数执行所需要的数据,为该函数执行提供支持;
全局执行上下文
:所有 JS 代码执行之前,都必须有该环境;
执行上下文栈
:call stack 所有执行上下文组成的内存空间;
执行上下文中的内容
this
指向;
Variable Object
:VO 变量对象 中记录了该环境中所有声明的 参数、变量 和 函数;
Global Object
: GO 全局对象 是全局执行上下文中的 VO;
Active Object
:AO 活动对象 当前正在执行的上下文中的 VO;
- 确定所有 形参值 以及特殊变量 arguments
- 确定函数中通过 var 声明的变量,将它们的值设置为 undefined ,如果 VO 中已有该名称,则直接忽略;
- 确定函数中通过 字面量 声明的函数,将它们的值指向 函数对象 ,如果 VO 中已存在该名称,则覆盖;
当一个上下文中的代码执行的时候,如果上下文中不存在某个属性,则会从之前的上下文寻找;
变量赋值操作
第一步
创建变量:声明 declare;
第二步
创建值:
- 基本值直接在栈中创建和存储;
- 引用值比较复杂,所以特殊处理,开辟一个内存空间(堆内存), 所有的堆内存都有一个可查找的 16 进制地址,后续赋值的时候是把堆内存地址给予变量;
第三步
让变量和值关联起来:定义 defined 也叫赋值;
面试题
第一题:(阿里)
let a = { n: 10 };
let b = a;
b.m = b = { n: 20 }; // 多个 '=' 的操作,从右向左赋值
console.log(a);
console.log(b);
第二题:(360)
函数执行之前的准备工作
- 初始化实参集合
- 创建形参变量并赋值
- 代码执行
let x = [12, 23];
function fn(y) {
y[0] = 100;
y = [100];
y[1] = 200;
console.log(y);
}
fn(x);
console.log(x);
第三题:
var x = 10;
~ function (x) {
console.log(x);
x = x || 20 && 30 || 40;
console.log(x);
}();
console.log(x);
第四题:
let x = [1, 2], y = [3, 4];
~ function (x) {
x.push('A');
x = x.slice(0);
x.push('B');
x = y;
x.push('C');
// [3, 4, "C"] [3, 4, "C"]
console.log(x, y);
}(x);
// [1, 2, "A"] [3, 4, "C"]
console.log(x, y);
第 1️⃣ 座大山:数据类型
上一篇