无法重新声明块范围变量。此处也声明了 。_前端基础 —— 变量

8d1de6ea1b9dca4b04b79a1831d58f64.png

前言

ECMAScript 变量是松散类型的,也就意味着变量可以用于保存任何数据的类型,而每个变量只不过是一个用于保存任意值的命名占位符。

有三个关键字可以声明变量:varlet(ES6新增)、const(ES6新增)

var

var 关键字可以声明变量,我们可以定义一个变量不赋值,也可以定义变量的同时为这个变量赋值,还可以改变保存的值和改变值的类型,但是不推荐去改变值的类型,虽然这在 ECMAScript 中是完全有效的:

var message // undefined
var message1 = 1 // 1
message1 = 'abc' // 合法,但不推荐

var 声明作用域

1. 在函数内部定义一个变量时,这个变量会在函数退出时被销毁:
function test() {
    var message = 1; // 局部变量
}
test();
console.log(message) // Uncaught ReferenceError: message is not defined
2. 在函数内部省略 var 操作符,可以创建一个全局变量:
function test() {
    message = 1; // 全局变量
}
test()
console.log(message); // 1

在这个例子中,去掉了上面?例子中的 var 关键字,那么只要 test() 函数被调用了一次,就会自动定义 message 变量,并且可以在函数外部访问到这个变量。

⚠️ 虽然我们可以省略 var 操作符来定义全局变量,但是不推荐这么做,因为会造成困惑,很难维护。

3. 可使用 var 操作符一次定义多个变量:
var message = 1, age = null, 
 a = ‘123’, b = fasle;

上面例子中定义了 4 个变量,因为 ECMAScript 是松散类型的,所以使用不同数据类型初始化的变量可以用一条语句来声明。

var 声明提升

使用 var 关键字声明的变量会自动提升到函数作用顶部:

function test() {
    console.log(message);
    var message = 1
}
test() // undefined

上面 ? 例子中,我们打印 message 时没有报错,并且还打印出了 undefined,这是因为 ECMAScript 在运行的时候把它看成等价于如下代码:

function test() {
    var message;
    console.log(message);
    message = 1;
}

这就是变量提升,就是把所有变量声明都拉到函数作用域的顶部,并且因为此特性,我们反复声明同一个变量也是没有问题的:

function test() {
    var message = 1;
    var message = 2;
    var message = 3;
    console.log(message);
}
test(); // 3

let

letES6 语法,它与 var 的作用差不多,都是声明变量的,但还是有区别的:

作用域

1、let 声明的范围是块作用域,而 var 声明的范围是函数作用域
// 使用 var 在块级作用域中声明变量:
if (true) {
    var name = 'Shinkai';
    console.log(name) // Shinkai
}
console.log(name) // Shinkai

// 使用 let 在块级作用域中声明变量:
if (true) {
    let age = 2;
    console.log(age) // 2
}
console.log(age) // Uncaught ReferenceError: age is not defined

上面例子中,age 变量不能在 if 块外部被使用,因为它的作用域仅限于 if 这个块内部,而我们的块级作用域是函数作用域的自己,所以适用于 var 的作用域限制同样也适用于 let

2、let 不允许同一个作用域中出现多次声明同一个变量:

在使用 var 声明变量时,由于声明会被提升,JavaScript 引擎会自动将多余的声明在作用域顶部合并为一个声明。而 let 的作用域是块,所以不可能检查前面是否已经使用 let 声明过同名的变量。因此,重复声明会报错。

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

当然,我们可以在不同块作用域中,嵌套使用相同的标识符,因为同一个块中没有重复声明:

var name = 'abc';
console.log(name) // name
if (true){
    var name = 'Shinkai';
    console.log(name) // Shinkai
    if (true) {
        var name = 'xss'
        console.log(name) // xss
    }
}

let age = 1;
console.log(age) // 1
if (true) {
    let age = 10;
    console.log(age) // 10
    if (true) {
        let age = 18;
        console.log(age) // 18
    }
}

暂时性死区

letvar 的另一个重要区别就是 —— let 声明的变量不会在作用域中被提升。

// name 会被提升
console.log(name); // undefined
var name = 'Shinkai';

// age 不会被提升
console.log(age); // Uncaught ReferenceError: age is not defined
let age = 18;

let 声明之前的执行瞬间被称为“暂时性死区”,在此阶段引用任何后面才声明的变量都会抛出 ReferenceError

全局声明

使用 let 声明的全局变量不会成为 window 对象的属性,而 var 声明的变量则会。

var name = "Shinkai";
let age = 18;
console.log(window.name) // "Shinkai"
console.log(window.age) // undefined

const

1、const 声明变量必须同时为其初始化
const age; // 报错:Uncaught SyntaxError: Missing initializer in const declaration
const age = 18;
2、const 声明的变量不允许修改
const age = 18;
age = 20; // 报错:Uncaught TypeError: Assignment to constant variable.
3、const 声明的限制只适用于它指向的变量的引用
// 对象
const pesron = {}
person.name = 'Shinkai'
// 数组
const nums = []
nums.push(1)

// 重新赋值就会报错
nums = [] // Uncaught TypeError: Assignment to constant variable.

上面例子其实就表明,如果是一个引用类型的变量,那么去对它进行一些列操作不会有问题,因为它始终指向同一个内存地址。但是若去改变它的引用地址,也就是重新赋值,就会报错。

总结

varletconst 的区别
  1. var 声明的变量会变量提升,而 letconst 不会。
  2. var 因为有变量提升,所以可以重复声明同一个变量,而 letconst 不允许这样操作。
  3. var 的作用域是函数作用域,而 letconst 都是块级作用域。
  4. letconst 都有暂时性死区,也就是在作用域中,使用 letconst 声明之前执行的瞬间。
  5. const 声明变量必须同时初始化,否则会报错。
  6. const 声明的变量不可以改变,但是对象只要不改变的内存地址,可以对属性进行操作。

参考文献

JavaScript 高级程序设计(第4版)

结语

前端基础是非常重要的基石,我们需要去学习理解并掌握它,当然,如果有不正确的地方欢迎指出哦~

如果你喜欢我的文章,就请动动你可爱的指头,扫码关注一下下,我们一起学习一起进步,走向人生巅峰~!

8ec5d744ff2faef85b0cad5a0ff683d4.gif
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值