开发中无时无刻不在定义变量,有局部变量,全局变量,私有变量等等,本章沉淀一下原始定义方式和现阶段的定义方式
原生JS定义变量及常量的方式
原生js定义变量使用var
关键字定义,不使用var时就会创建全局变量。很容易混淆,所以形成了一些约定:
- 全局变量:变量名使用大写字母,如:USERS
- 局部变量:变量名使用小写字母,如:user
- 函数变量:函数内部定义变量必须使用var
约定毕竟需要人进行约束,所以不可避免会出现一些意外状况。其次对于循环,两个同级别的循环定义同一个变量名(如i)会冲突,所以需要定义其他的变量名(如:m、n、j等),对于书写代码来说非常不友好。‘
原生JS变量
在ES6出来之前,var相关问题经常会被问到,在ES6出来之后,var仅成了对比,本篇沉淀一下var定义变量的一些历史知识点,对于此不熟悉的可以了解一下
变量作用域
变量作用域是前几年比较常见的问题之一,全局作用域、函数作用域,变量名相同时是什么样的等等。
全局作用域
在最外层定义的变量都具备全局作用域
var a = 1;
function test () {
console.log(a)
}
test() // 1
由于a在function外面,所以具备全局作用域,函数内可以访问到全局作用域的变量a。
在函数内定义变量a会如何?
var a = 1;
function test () {
var a = 2;
console.log(a)
}
test() // 2
console.log(a) // 1
函数内部若定义了和外部一样的变量名,则优先读取函数内部的变量值。
那函数内部变量不带var?
var a = 1;
function test () {
a = 2;
console.log(a)
}
test() // 2
console.log(a) // 2
函数内部会读取全局作用域的a变量,同时进行修改
不在外部定义变量会怎么样
function test () {
a = 2;
console.log(a)
}
test() // 2
console.log(a) // 2
当不带var
关键字时会创建全局作用域的变量,其实函数的执行如下:
var a
function test () {
a = 2;
console.log(a)
}
test() // 2
console.log(a) // 2
原理就是变量提升,下面对变量提升进行了专门的解析
变量提升
早期JS中经常被提及的问题,如下代码:
function test () {
console.log(a)
var a = 1;
}
test(); // undefined
你认为undefined是因为a定义在了console后面么,非也,其实代码真正执行顺序:
function test () {
var a;
console.log(a)
a = 1;
}
test();
上述是在函数内的变量提升,现在看一下函数外的变量提升
a = 1;
var a;
console.log(a)
输出是1,实际生命变量会提升到作用域顶端,具体如下
var a;
a = 1;
console.log(a)
来一道多年前的面试题,现在很少见的哦~
console.log(a);
var a = 1;
function test() {
console.log(a);
var a = 2;
console.log(a);
}
test();
console.log(a);
结果:undefined undefined 2 1
现在是不是很容易理解了,实际代码运行
var a;
console.log(a); // undefined
a = 1;
function test() {
var a;
console.log(a); // undefined
a = 2;
console.log(a); // 2
}
test();
console.log(a); // 1
ES6新增let和const命令
ES6为了解决原生JS遗留的问题,新增了let和const命令:
let
声明的变量,只在let
命令所在的代码块内有效const
一旦声明,常量的值就不能改变
上述两个命令解决了块级作用域及常量不可修改的问题。
let
let
用于定义变量,作用域范围为代码块内。
let a = 1;
function test () {
console.log(a)
};
test(); // 1
console.log(a) // 1
在函数外面使用let
定义和var
没有太大区别,作用域基本一致。
但是:
var a = 1;
window.a // 1;
let b = 2;
window.b // undefined
const c = 3;
window.c // undefined
因此,基于var
定义的变量会挂载在window上。
for循环是属于独立代码块,看一下let
的表现
// 原生var
for(var j = 0; j < 3; j++) {}
console.log(j) // 3
// ES6的let
for(let i = 0; i < 3; i++) {}
console.log(i) // 报错
根据上述代码运行结果可以发现:let仅作用于代码块内
关于块级作用域
function test() {
var n = 5;
if (true) {
var n = 10;
}
console.log(n);
}
test(); // 10
function test() {
let n = 5;
if (true) {
let n = 10;
}
console.log(n);
}
test(); // 5
每个{}
包裹的代码都属于块级作用域
const
const
声明一个只读的常量。一旦声明,常量的值就不能改变。
const a = 1;
a = 2; // Uncaught SyntaxError: Identifier 'a' has already been declared
对于基础数据类型,const定义的变量是不可更改的。
const a = {
key1: 1
}
a.key2 = 2; // { key1: 1, key2: 2 }
delete a.key1; // {key2: 2}
a = {}; // Uncaught TypeError: Assignment to constant variable.
对于复杂数据,可以添加或删除值,但不可重新赋值。
总结分析
let
定义的变量作用域为块作用域,const
定义的变量不可直接赋值var
定义的全局变量会挂载在window上
相关试题
- ES6新增了哪些特性。
- let、const和var的区别。
- let和const的特点。
- 变量提升相关试题(笔试)