重学javascript变量声明var let const

48 阅读3分钟

1.变量

js的变量是松散类型,意思就是可以保存任意类型的数据,每一个变量只不过是一个用于保存任意值的命名占位符,有三个关键字可以声明变量:var(ECMAScript所有版中都可以用) let const(let const只能在ES6及以后版本中使用)

var关键字

定义变量:var(操作符)后面跟一个变量名(即标识符)比如

var message;

这段代码定义了一个message变量,可以保存任意值, 因为没有初始化,所以输出是一个特殊值undefined,

var声明作用域

var 操作符定义的变量会成为包含它函数的局部变量,因为变量是在函数内部定义,调用这个函数会创建这个变量并给它赋值,调用之后随即销毁,所以会出现报错。去掉var 操作符age就成了全局变量就可以访问的到(不推荐这样做,严格模式下会抛出错误ReferenceError)

function foo() {
    var age = 16//局部作用域
}
foo()
console.log(age)//ReferenceError: age is not defined
-------------------------------------------------------------------
function foo() {
    age = 16//全局作用域
}
foo()
console.log(age)//16
-------------------------------------------------------------------
"use strict"
function foo() {
     age = 16
}
foo()
console.log(age)//ReferenceError: age is not defined

let声明

let var作用差不多,都是声明变量,它们两个明显的区别就是let 声明范围是块级作用域,var 声明范围是函数作用域,

if(true){
    var name = 'GG'
    console.log(name)//GG
}
console.log(name)//GG
---------------------------------------------------------------------
if(true){
    let name = 'GG'
    console.log(name)//GG
}
console.log(name)//ReferenceError: name is not defined

为什么let声明的 name变量不能在if块外部被引用,是因为它的作用域限制于该块内部,(注意块级作用域是函数作用域的子集所以适用于var的作用域限制同样也适用于let)

let不允许出现重复声明

let name
let name
//输出:SyntaxError: Identifier 'name' has already been declared

对于声明冗余的错误,不会因为var 和let混用而受影响,这两个关键字并不是声明不同类型的变量,他们只是指出变量相关作用域如何存在

var name
let name
//SyntaxError: Identifier 'name' has already been declared

let暂时性死区

var和let的另一个区别就是let声明的变量不会在作用域中被提升,

console.log(name)
let name = "GG"
//输出:ReferenceError: Cannot access 'name' before initialization

在代码解析的时候,js引擎会注意到出现在块后面的let声明,只不过在此之前不能以任何方式来引用未声明的变量,在let声明之前的执行瞬间被称为暂时性死区

let进行全局声明

let 在全局作用域声明的变量不会成为window对象属性,var声明则会,不过let的声明仍会在页面的生命周期内存续,因此为了避免SyntaxError ,就必须确保页面内不会重复声明同一个变量

var name = "GG"
let age = 66
console.log(window.name)
console.log(window.age)//undefined

const声明

const与let基本相同,唯一的重要区别就是它声明变量时必须同时初始化变量,且尝试修改时会报错,但是这个限制只适用于它指向的变量的引用,就是说如果const引用的变量是一个对象,那么修改这个对象内部的属性并不违反const 限制

js引擎会为for循环中的let声明分别创建单独的变量实例,虽然const跟let很相似但是不能用const来声明迭代变量,(因为迭代变量会自增),但是如果循环一个不会被修改的for循环变量却是可以的。也就是说,每次迭代只是创建一个新变量。这对 for-of 和 for-in 循环特别有意义

for (const i = 0; i < 10; i++) {
    console.log(i)
}
//错误:TypeError: Assignment to constant variable.
-------------------------------------------------------
//循环对象
for (const arrayKey in {a:1,b:6}) {
    console.log(arrayKey)
}
循环数组
for (const arrayKey of [1,2,3]) {
    console.log(arrayKey)
}


let i= 0
for (const j=7 ;i<5;i++) {
    console.log(j)
}
//输出:7,7,7,7,7