关于变量的理解
何为变量? 简而言之就是存储数据值的容器,js所有变量都拥有唯一标识符,即我们通常说的变量名。
变量名称命名规则
- 名称可包含字母、数字、下划线和美元符号($);
- 名称必须以字母开头
- 名称也可以 $ 和 _ 开头(不推荐使用)
- 名称区分大小写
- 保留字无法用作变量名称
关于变量,我们通常有两个操作,声明和赋值
变量作用域
变量作用域是指一个变量可以在哪一个范围内使用。
主要分全局作用域和函数作用域,而在ES6中新增的let和const的关键词可以在一对大括号之间{}形成块级作用域。
全局作用域
- 全局作用域在页面打开时被创建,页面关闭时被销毁;
- 拥有全局作用域的变量全局有效,在页面的任意位置都可以访问到;
- 在函数外部声明的变量或在函数内部没有使用var关键字声明的变量具有全局作用域,可称为全局变量;
- 全局作用域中声明的变量和函数会被挂载到全局对象window对象上,作为window对象的属性和方法保存,可通过 “window.变量名” 的方式访问到。
函数作用域
- 调用函数时,函数作用域被创建,函数执行完毕,函数作用域被销毁;
- 拥有函数作用域的变量只在该函数内部有效,在函数外部无法访问;
- 在函数内部通过var关键字声明的变量具有函数作用域,可称为局部变量;
- 每调用一次函数就会创建一个新的函数作用域,他们之间是相互独立的;
- 在函数中定义形参,等同于声明变量。
块级作用域
- ES6新增内容,包含在{}里的区域;
- 使用let和const定义的变量具有 块级作用域。
变量搜索机制
当某个变量被访问时通常会经过以下步骤:
- 判断当前位置是否存在局部作用域(即函数作用域和块级作用域);
- 存在局部作用域,则判断该局部作用域内是否存在该变量名的变量;
- 若无,寻找上一级作用域,重复第二个步骤,直到全局作用域;
- 若全局作用域也找不到这个变量,这个变量就是未定义的 undefined。
变量提升
如果变量声明在函数里面,则将变量声明提升到函数的开头
如果变量声明是一个全局变量,则将变量声明提升到全局作用域的开头
变量声明之let、const、var
我们通常使用 var 关键词来声明 JavaScript 变量
var b;//声明变量b
变量声明之后,是没有值的,即为undefined。
在ES6中新增了两个关键词 let 和 const ,他们与 var 主要有以下区别:
- var声明的变量会挂载在window上,而let和const声明的变量不会:
var a=1;
let b=2;
const c=3;
console.log(a,b,c); // 1,2,3
console.log(window.a); //1
console.log(window.b); //undefined
console.log(window.c); //undefined
- let 和 const 会在一对大括号内形成块级作用域,而var不会:
if(1){
var a=1;
let b=2;
const c=3;
}
console.log(a); // 1
console.log(b); // b is not defined
console.log(c); // c is not defined
let 和 const 会在 {} 内形成块级作用域,成为其内部的局部变量,因此在{}外无法访问。
- var声明变量存在变量提升,let和const不存在变量提升
console.log(a);
console.log(b);
console.log(c);
var a=1;
let b=2;
const c=3;
console.log(a);
var a; //变量提升
console.log(a); //undefined,已经声明,还未赋值;
console.log(b); //b is not defined
console.log(c); //c is not defined
a=1;
let b=2;
const c=3;
console.log(a); // 1
- const 为常量,一旦定义不可更改,而var,let为变量,可以改变其值:
var a = 1;
let b = 2;
const c = 3;
console.log(a); // 1
console.log(b); // 2
console.log(c); //3
a = 4;
b = 5;
c = 6; // 报错:Assignment to constant variable. 常量不可以再次赋值
console.log(a); //4
console.log(b); //5
- 同一作用域下let和const不能声明同名变量,而var可以
var a=1;
let b=2;
const c=3;
console.log(a); //1
console.log(b); //2
console.log(c); //3
var a=4;
console.log(a); //4
// let b=5; //报错 : Identifier 'b' has already been declared
const c=6; //报错 : Identifier 'c' has already been declared
- 存在暂时性死区
暂时性死区的本质就是,只要一进入当前作用域,所要使用的变量就已经存在了,但是不可获取,只有等到声明变量的那一行代码出现,才可以获取和使用该变量。因此,一旦在某个作用域内存在let定义的变量,那该作用域内所有使用该变量名的变量都将值这一变量,而不再受外部变量的影响。
var a=1;
if(1){
console.log(a); //a is not defined .此处的a指的是该作用域内let所声明的变量a,而不是外部的var声明a,只是let没有变量提升,所以此处的a还未声明,无法访问。
let a=2;
}