ES6系列文章 块级做用域

ES5以前javascript语言只有函数做用域和全局做用域,使用var来声明变量,var声明的变量还存在变量提高令人困惑不已。咱们先来复习一下ES5的var声明,再对比学习let和const 。javascript

var

var声明之函数做用域和全局做用域。

来段代码体会一下:前端

function getName() {
    if (1 + 1 === 2) {
        var name = 'xixi';
    }

    console.log(name);
}

getName();//xixi

在c或java语言中name本应该只在if块中使用的,可是在if的外面也能够访问到,这个就是 js没有块级做用域的一种体现。这个弊端在for循环中体现的十分明显:java

for (var i = 0; i < 10; i ++) {
    // ...
}

console.log(i);// 10

var i的本意是声明个临时变量i,用来遍历数组等,本不该该在for循环的外部访问到,但如今却能够被访问到你说闹不闹心?好一点的程序员会用当即执行函数来模拟块级做用域,原来的我会注意一下尽可能不使用相同的变量名?。程序员

(function() {
    for (var i = 0; i < 10; i ++) {
        // ...
    }
})();

console.log(i);// undefined

以上:你们知道了 js 没有块级做用域。数组

变量能够重复声明

var name = 'xixi';
console.log(name);// xixi
var name= '一步';
console.log(name);// 一步

不报错,困惑不困惑,这个就是变量能够重复声明。函数

变量提高

function getName() {
    console.log(name);
    var name = 'xixi';
    // ...
}

getName();// undefined

console.log打印name为undefined。为啥不报错呢,对于一直使用js语言的人来讲这个现象还好理解,若是是后台转前端的人来讲估计得骂人了。这就是所谓的变量提高。简单的向你们解释一下吧。学习

var name = 'xixi';

这是一条被咱们写烂了的语句,包含两个过程:var name; name = 'xixi';分别为变量声明和变量初始化。spa

变量提高: 不管变量声明var name;处于什么位置,都会被提到做用域的顶部进行。code

let

ES6为让变量生命周期更加可控,引入两个很是好的特性letconst。块级做用域、不能重复声明、临时性死区等特性用来解决 var 变量存在的种种问题。对象

块级做用域

function getName4ES6() {
    if (1 + 1 === 2) {
        let name = 'xixi';
    }

    console.log(name);
}

getName4ES6(); // undefined

终于在{}外面访问不到name了。for循环也变的简单了,你们试一下将for循环的var换成 let.

同一块级做用域内不能重复声明变量

function redefineValue() {
    let name = 'xixi';
    let name = '一步';
}

redefineValue();// Uncaught SyntaxError: Identifier 'name' has already been declared

重复声明会报错

{
    let name = 'xixi';
    console.log(name);// xixi
    {
        let name = 'yibu';
        console.log(name); // yibu
    }
}

注意: 在 ES6中,{}就是一个块级做用域。

临时性死区

function getName4ES6() {
    console.log(name);
    for (let i = 0; i < 10; i ++) {

    }
    let name = 'xixi';
    // ...
}

getName4ES6();// Uncaught ReferenceError: name is not defined

在上文ES5中,name还会存在变量提高,值为undefined。ES6中又报错了。怎么解释呢?。。。。这个就是临时性死区的概念,在做用域块中不能够在变量声明前就使用变量,若使用是会出错的。

javascript引擎在发现变量声明时,要么将变量声明提高到做用域的顶部(var声明变量时),要么将变量放在临时性死区中(let、const声明变量时),访问临时性死区中的变量会触发运行时错误。

图片描述

const

const和let一样具备块级做用域,不能重复声明,临时性死区的概念。它还具备两个特有的特性:声明的同时必须初始化、变量引用不能够改变。

声明的同时必须初始化

const name;//Uncaught SyntaxError: Missing initializer in const declaration

不赋值,就报错。这个也很好理解const的本意就是用来定义常量,不可变的值。若不在声明时给出初始值之后就再也没有机会了。

值不可变

const name = 'x9x9';
name = 'yyy';// Uncaught SyntaxError: Invalid or unexpected token

那么对象会怎样呢?

const person = {
    name: 'lala',
    age: 40
};

person = {};// VM1042:6 Uncaught TypeError: Assignment to constant variable. at <anonymous>:6:8

引用是不可变的,那咱们在看看对象的属性值是什么状况吧~

person.name = 'yoyo';
console.log(person);// {name: "yoyo", age: 40}

没有报错,对象引用不可改变,对象属性能够变动。

let vs const

你们可能会困惑,何时使用let,何时使用const。let能作的const好像均可以。网上有一种流行作法:能用const就毫不用let,简单粗暴,不过很好用。我的见解:若变量在后续方法中会被改变,就使用let。一些常量声明使用const, const声明的变量名所有大写。代码中的变量,若是是let声明的就表明其可变,如果const声明的,不管是简单数据类型仍是引用类型变量就都不要改变它的值。这样,程序会更加的健壮,你们合做起来也比较方便。

相关文章
相关标签/搜索