首頁 > web前端 > js教程 > ES6中新的變數宣告方式介紹(附程式碼)

ES6中新的變數宣告方式介紹(附程式碼)

不言
發布: 2019-03-26 10:11:33
轉載
2558 人瀏覽過

這篇文章帶給大家的內容是關於ES6中新的變數宣告方式介紹(附程式碼),有一定的參考價值,有需要的朋友可以參考一下,希望對你有幫助。

在ES5中,變數宣告只有var和function以及隱式宣告三種,在ES6中則增加了let、const、import和class四種。

1. let

1.1 區塊級作用域

let宣告的變數的作用域是區塊級作用域(這個特性有點類似後台語言),ES5 並沒有區塊級作用域,只有函數作用域和全域作用域。

{
  let a = 'ES6';
  var b = 'ES5';
}

console.log(b)  // ES5 
console.log(a)  // ReferenceError: a is not defined.
登入後複製

那麼let的區塊級作用域有什麼好處呢?

let非常適合用於 for迴圈內部的區塊級作用域。 JS中的for迴圈體比較特殊,每次執行都是一個全新的獨立的區塊作用域,用let宣告的變數傳入到 for迴圈體的作用域後,不會改變,不受外界的影響。看一個常見的面試題目:

for (var i = 0; i <10; i++) {  
  setTimeout(function() {  // 同步注册回调函数到异步的宏任务队列。
    console.log(i);        // 执行此代码时,同步代码for循环已经执行完成
  }, 0);
}
// 输出结果
10   (共10个)
// 这里变量为i的for循环中,i是一个全局变量,在全局范围内都有效,所以每一次循环,新的i值都会覆盖旧值,导致最后输出的是最后一轮i的值,即i的最终结果为10,实际上都是console.log(10)。涉及的知识点:JS的事件循环机制,setTimeout的机制等
登入後複製

把var改成let宣告:

for (let i = 0; i < 10; i++) { 
  setTimeout(function() {
    console.log(i);    //当前的i仅在本轮的循环中有效,就是说每一次循环,i其实都是一个新产生的变量。                          //用 let 声明的变量 i 只作用于循环体内部,不受外界干扰。
  }, 0);
}
// 输出结果:
0  1  2  3  4  5  6  7  8 9
登入後複製

1.2 暫時性死區(Temporal Dead Zone)

在一個區塊層級作用域中,變數唯一存在,一旦在區塊級作用域中用let聲明了一個變量,那麼這個變數就唯一屬於這個區塊級作用域,不受外部變數的影響,如下面所示。

var tmp = 'bread and dream';
if(true){
    tmp = 'dream or bread';   //ReferenceError
    let tmp;
}
登入後複製

這個例子中tmp = 'dream or bread'的賦值會報錯,因為在if區塊中的let對tmp變數進行了聲明,導致該tmp綁定了這個作用域,而let臨時死區導致了並不能在聲明前使用,所以在聲明前對變數賦值會報錯。

暫時性死區的本質就是,只要一進入目前作用域,所要使用的變數就已經存在了,但是不可獲取,只有等到宣告變數的那一行程式碼出現,才可以取得並使用該變數。

暫時性死區的意義也是讓我們標準化程式碼,將所有變數的宣告放在作用域的最開始。

1.3 不允許重複宣告

(1) 在相同的作用域內,用let宣告變數時,只允許宣告一遍,但 var是可以多次宣告的。大家都知道ES5 多次聲明會造成變數覆蓋而且不會報錯,這就給調試增加了難度,而let能夠直接扼殺這個問題在搖籃之中,因為會直接報錯。

// 不报错
function demo() {
  var a = 'bread and dream';
  var a = 'dream or bread';
}
 
// 报错,Duplicate declaration "a"
function demo() {
  let a = 'bread and dream';
  var a = 'dream or bread';
}

// 报错,Duplicate declaration "a"
function demo() {
  let a = 'bread and dream';
  let a = 'dream or bread';
}
登入後複製

(2) 無法在函數內部重新宣告參數:

function demo1(arg) {
  let arg; // 报错
}
demo1()
function demo2(arg) {
  {
    let arg; // 不报错
  }
}
demo2()
登入後複製

#2. const

2.1 用來宣告常數

#const聲明的常數是不允許改變的,只讀屬性,這意味著常數聲明時必須同時賦值, 只聲明不賦值,就會報錯,通常常量以大寫字母命名。

const Person;   // 错误,必须初始化 
const Person = 'bread and dream';// 正确

const Person2 = 'no'; 
Person2 = 'dream or bread'; //报错,不能重新赋值
登入後複製

這樣做的兩個好處:一是閱讀程式碼的人立刻會意識到不應該修改這個值,二是防止了無意間修改變數值所導致的錯誤。例如我們使用nodejs的一些模組的時候,我們只是使用對應的模組(如http模組),但並不需要修改nodejs的模組,這個時候就可以宣告成const,增加了程式碼的可讀性和避免錯誤。

2.2 支援區塊級作用域

const和let類似,也是支援區塊級作用域.

if (true) {
  const MIN = 5;
}

MIN // Uncaught ReferenceError: MIN is not defined
登入後複製

2.3 不支援變數提升,有暫時性死區

const宣告的常數也是不提升,同樣存在暫時性死區,只能在宣告的位置後面使用。

if (true) {
  console.log(MIN); // ReferenceError
  const MIN = 5;
}
登入後複製

2.4 特殊情況

如果聲明的常數是一個對象,那麼對於對象本身是不允許重新賦值的,但是對於對象的屬性是可以賦值的。

const obj = {};
obj.a = 'xiao hua';
console.log(obj.a);    //'xiao hua'
登入後複製

實際上const能保證的,並不是變數的值不得改動,而是變數指向的那個記憶體位址所保存的資料不得改動。

對於簡單類型的資料(數值、字串、布林值),值就保存在變數指向的那個記憶體位址,因此等同於常數。

但對於複合類型的資料(主要是物件和陣列),變數指向的記憶體位址,保存的只是一個指向實際資料的指標。

至於它所指向的資料結構是不是可變的,就完全不能控制了。因此,將一個物件聲明為常數必須非常小心。

如果要徹底凍結物件(不可修改其屬性),應該使用Object.freeze(obj)方法。同理,數組也是一樣的。

3. import

ES6採用import來取代node等的require來導入模組。

import {$} from './jquery.js'
登入後複製

$物件就是jquery中export暴露的物件。

如果想為輸入的變數重新取一個名字,import指令要使用as關鍵字,將輸入的變數重新命名。

import { JQ as $ } from './jquery.js';
登入後複製

注意,import指令具有提升效果,會提升到整個模組的頭部,首先執行。

4. class

ES6引進了類別的概念,有了class這個關鍵字。類別的實質還是函數物件。

先定義一個類別:

//定义类
class Animal {
  constructor(name, age) {
        this.name = name;
        this.age = age;
  }    
  setSex(_sex) {
        this.sex=_sex;
  }
}
登入後複製

constructor方法,就是建構方法,也就是ES5時代函數物件的主體,而this關鍵字則代表實例物件。

上面的類別也可以改成ES5的寫法:

function Animal(name, age){
        this.name = name;
        this.age = age;
}

Animal.prototype.setSex = function (_sex) {
        this.sex=_sex;
}
登入後複製

其實,大多數類別的特性都可以透過先前的函數物件與原型來推導。

生成类的实例对象的写法,与ES5通过构造函数生成对象完全一样,也是使用new命令。

class Animal {}
let dog = new Animal();
登入後複製

在类的实例上面调用方法,其实就是调用原型上的方法,因为类上的方法其实都是添加在原型上。

Class其实就是一个function,但是有一点不同,Class不存在变量提升,也就是说Class声明定义必须在使用之前。

5.总结

在ES6之前,JavaScript是没有块级作用域的,如果在块内使用var声明一个变量,它在代码块外面仍旧是可见的。ES6规范给开发者带来了块级作用域,let和const都添加了块级作用域,使得JS更严谨和规范。

let 与 const 相同点:

块级作用域
有暂时性死区
约束了变量提升
禁止重复声明变量

let 与 const不同点:

const声明的变量不能重新赋值,也是由于这个规则,const变量声明时必须初始化,不能留到以后赋值。

合理的使用ES6新的声明方式,不管是面试还是工作中都有实际的应用,尤其是工作中,大家一定要尽量的多使用新的声明方式,不但可以让代码更规范,更可以避免不必要的bug,浪费调试时间,进而提高工作效率。

本篇文章到这里就已经全部结束了,更多其他精彩内容可以关注PHP中文网的JavaScript视频教程栏目!

以上是ES6中新的變數宣告方式介紹(附程式碼)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:segmentfault.com
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
作者最新文章
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板