Twlig / issuesBlog

MIT License
3 stars 0 forks source link

变量与作用域 #9

Open Twlig opened 2 years ago

Twlig commented 2 years ago

变量

ECMAScript 变量是松散类型的,意思是变量可以用于保存任何类型的数据。有 3 个关键字可以声明变量:var、const 和 let。其中,var 在ECMAScript 的所有版本中都可以使用,而 const 和 let 只能在 ECMAScript 6 及更晚的版本中使用。

var 关键字

let关键字

let和var差不多,但是let 声明的范围是块作用域,而 var 声明的范围是函数作用域

if (true) { 
 let age = 26; 
 console.log(age); // 26 
} 
console.log(age); // ReferenceError: age 没有定义

age 变量之所以不能在 if 块外部被引用,是因为它的作用域仅限于该块内部。块作用域是函数作用域的子集,因此适用于 var 的作用域限制同样也适用于 let。

const关键字

const 的行为与 let 基本相同,唯一一个重要的区别是用它声明变量时必须同时初始化变量,初始化后不可修改

const age = 26; 
age = 36; // TypeError: 给常量赋值

const 声明的限制只适用于它指向的变量的引用。如果 const 变量引用的是一个对象,可修改对象内部属性

const person = {}; 
person.name = 'Matt'; // ok

原始值与引用值

ECMAScript 变量可以包含两种不同类型的数据:原始值和引用值。原始值就是最简单的数据,引用值则是由多个值构成的对象。

原始值:Undefined、Null、Boolean、Number、String 和 Symbol

引用值:Object

保存原始值的变量是按值访问的,因为我们操作的就是存储在变量中的实际值。引用值的变量是按引用访问的。引用值和原始值在使用过程中还存在一些不同,下面将详细展开:

执行上下文与作用域

​ 上下文其实就可以理解为代码运行所能访问的变量和函数环境。每个上下文都有一个关联的变量对象,上下文中定义的所有变量和函数都存在于这个对象上。全局上下文就是 window 对象,是最外层的上下文,所有通过 var 定义的全局变量和函数都会成为 window 对象的属性和方法。上下文在其所有代码都执行完毕后会被销毁,包括定义在它上面的所有变量和函数(全局上下文在应用程序退出前才会被销毁,比如关闭网页或退出浏览器)。

​ 上下文中的代码在执行的时候,会创建变量对象的一个作用域链,这个作用域链决定了各级上下文中的代码在访问变量和函数时的顺序。

var color = "blue"; 
function changeColor() { 
 let anotherColor = "red"; 
 function swapColors() { 
 let tempColor = anotherColor; 
 anotherColor = color; 
 color = tempColor; 
 // 这里可以访问 color、anotherColor 和 tempColor 
 } 
 // 这里可以访问 color 和 anotherColor,但访问不到 tempColor 
 swapColors(); 
} 
// 这里只能访问 color 
changeColor();

作用域链图:

内部上下文可以通过作用域链访问外部上下文中的一切,但外部上下文无法访问内部上下文中的任何东西。每个上下文都可以到上一级上下文中去搜索变量和函数,但任何上下文都不能到下一级上下文中去搜索。

如果在局部上下文中找到该标识符,则搜索停止,变量确定;如果没有找到变量名,则继续沿作用域链搜索。(注意,作用域链中的对象也有一个原型链,因此搜索可能涉及每个对象的原型链。)这个过程一直持续到搜索至全局上下文的变量对象。

var color = 'blue'; 
function getColor() { 
 let color = 'red'; 
 return color; 
} 
console.log(getColor()); // 'red'

上下文之间的连接是线性的、有序的。找到了最近的就不会再往上去找了。