- Published on
变量、作用域、内存
- Authors

- Name
- 李丹秋
原始值和引用值
原始值大小固定,因此保存在栈内存上。引用值是对象,存储在堆内存上。 ECMAScript 变量可以包含两种不同类型的数据:原始值和引用值。原始值包括(Undefined、Null、Boolean、Number、String、Symbol、BigInt).保存原始值的变量是按值(by value)访问的,因为我们操作的就是存储在变量中的实际值。引用值是保存在内存中的对象。与其他语言不同,JavaScript 不允许直接访问内存位置,因此也就 不能直接操作对象所在的内存空间。在操作对象时,实际上操作的是对该对象的引用(reference)而非实际的对象本身。为此,保存引用值的变量是按引用(by reference)访问的.
复制值
let num1 = 5;
let num2 = num1;
原始类型赋值的时候,会创建一个新的副本,两个变量相互独立;
对象(引用类型),赋值的是一个指针地址,指向堆内存中的变量。所以被赋值的对象做了修改,也会影响赋值对象。
传递参数
ECMAScript中所有函数的参数都是按值传递的。这个如果传递的是一个值类型,就比较好理解,无论传递进去的值如何修改都不会改变被传递的值。
function setName(obj) {
obj.name = "Nicholas";
obj = new Object();
obj.name = "Greg";
}
let person = new Object();
setName(person);
console.log(person.name); // "Nicholas"
执行上下文和作用域
每个上下文都有一个关联的变量对象(variable object),而这个上下文中定义的所有变量和函数都存在于这个对象上。 上下文再其所有的代码都执行完毕后会被销毁,包括定义在它上面的所有的变量和函数。全局上下文只有在应用程序退出的时候才会被销毁。 每个函数调用都有自己的上下文,当代码执行流进入函数时,函数的上下文被推到一个上下文栈上。 在函数执行完之后,上下文栈会弹出该函数上下文,将控制权返还给之前的执行上下文。ECMAScript程序的执行流就是通过这个上下文栈进行控制的。
变量声明
- 在使用 var 声明变量时,变量会被自动添加到最接近的上下文。 var 声明会被拿到函数或全局作用域的顶部,位于作用域中所有代码之前。这个现象叫作“提升”。提升让同一作用域中的代码不必考虑变量是否已经声明就可以直接使用。
- 使用let的块级作用域声明,级作用域由最近的一对包含花括号界定。 严格来讲,let 在 JavaScript 运行时中也会被提升,但由于“暂时性死区”(temporal dead zone)的缘故,实际上不能在声明之前使用 let 变量。因此,从写 JavaScript 代码的角度说,let 的提升跟 var 是不一样的。