ES6(JaveScript 的下一個版本標準)學習(一) let、const、結構賦值、Symbol

初學不知道別人提到的ES6是什麼,查一下原來是JavaScript(JavaScript 也稱 ECMAScript) 的下一個版本標準,所以學習起來應該不會太陌生

主要學習地址:菜鳥教程 http://www.runoob.com/w3cnote/es6-tutorial.html

學習方式:一邊看教程一邊記錄要點,掌握自己之前不知道的知識點,弄不清楚的地方用代碼調試(調試環境:Node.js)輔助理解

ES6, 全稱 ECMAScript 6.0 ,是 JaveScript 的下一個版本標準,2015.06 發版。

ES6 主要是爲了解決 ES5 的先天不足,比如 JavaScript 裏並沒有類的概念,但是目前瀏覽器的 JavaScript 是 ES5 版本,大多數高版本的瀏覽器也支持 ES6,不過只實現了 ES6 的部分特性和功能。

Node.js 是運行在服務端的 JavaScript,它對 ES6 的支持度更高。

/*教程裏突然出現了webpack和gulp,後面再看看它們跟ES6有什麼聯繫
webpack
webpack 是一個現代 JavaScript 應用程序的靜態模塊打包器 (module bundler) 。當 webpack 處理應用程序時,它會遞歸地構建一個依賴關係圖 (dependency graph) ,其中包含應用程序需要的每個模塊,然後將所有這些模塊打包成一個或多個 bundle 。
gulp
gulp 是一個基於流的自動化構建工具,具有易於使用、構建快速、插件高質和易於學習的特點,常用於輕量級的工程中。*/

ES2015(ES6) 新增加了兩個重要的 JavaScript 關鍵字: let 和 const。

let 聲明的變量只在 let 命令所在的代碼塊內有效。

const 聲明一個只讀的常量,一旦聲明,常量的值就不能改變。
let 是在代碼塊內有效,var 是在全局範圍內有效

let 只能聲明一次, var 可以聲明多次

for 循環計數器適合用 let

let 不存在變量提升,var 會變量提升:先使用變量再用let定義報錯,先使用變量再用var定義值是undefined

const 聲明一個只讀變量,聲明之後不允許改變。意味着,一但聲明必須初始化,否則會報錯。ES6 明確規定,代碼塊內如果存在 let 或者 const,代碼塊會對這些命令聲明的變量從塊的開始就形成一個封閉作用域。代碼塊內,在聲明變量之前使用它會報錯。

const 如何做到變量在聲明初始化之後不允許改變的?其實 const 其實保證的不是變量的值不變,而是保證變量指向的內存地址所保存的數據不允許改動。此時,你可能已經想到,簡單類型和複合類型保存值的方式是不同的。是的,對於簡單類型(數值 number、字符串 string 、布爾值 boolean),值就保存在變量指向的那個內存地址,因此 const 聲明的簡單類型變量等同於常量。而複雜類型(對象 object,數組 array,函數 function),變量指向的內存地址其實是保存了一個指向實際數據的指針,所以 const 只能保證指針是固定的,至於指針指向的數據結構變不變就無法控制了,所以使用 const 聲明覆雜類型對象時要慎重。

解構賦值是對賦值運算符的擴展。

他是一種針對數組或者對象進行模式匹配,然後對其中的變量進行賦值。

在代碼書寫上簡潔且易讀,語義更加清晰明瞭;也方便了複雜對象中數據字段獲取。

直接看教程:http://www.runoob.com/w3cnote/deconstruction-assignment.html

ES6 引入了一種新的原始數據類型 Symbol ,表示獨一無二的值,最大的用法是用來定義對象的唯一屬性名。

ES6 數據類型除了 Number 、 String 、 Boolean 、 Objec t、 null 和 undefined ,還新增了 Symbol 。

Symbol 函數棧不能用 new 命令,因爲 Symbol 是原始數據類型,不是對象。可以接受一個字符串作爲參數,爲新創建的 Symbol 提供描述,用來顯示在控制檯或者作爲字符串的時候使用,便於區分。
注:教程例子那裏因爲sy是大寫的KK而sy1是小寫的kk所以有點費解,調試發現就算是大寫的KK也是不等的

let sy = Symbol("KK");
console.log(sy);   // Symbol(KK)

// 相同參數 Symbol() 返回的值不相等
let sy1 = Symbol("kk");
console.log(sy1);
console.log(sy === sy1);       // false

let sy2 = Symbol("KK");
console.log(sy2);
console.log(sy === sy2);       // false

上面的代碼輸出:
Symbol(KK)
Symbol(kk)
false
Symbol(KK)
false

由於每一個 Symbol 的值都是不相等的,所以 Symbol 作爲對象的屬性名,可以保證屬性不重名。

Symbol 作爲對象屬性名時不能用.運算符,要用方括號。因爲.運算符後面是字符串,所以取到的是字符串 sy 屬性,而不是 Symbol 值 sy 屬性。

Symbol 值作爲屬性名時,該屬性是公有屬性不是私有屬性,可以在類的外部訪問。但是不會出現在 for…in 、 for…of 的循環中,也不會被 Object.keys() 、 Object.getOwnPropertyNames() 返回。如果要讀取到一個對象的 Symbol 屬性,可以通過 Object.getOwnPropertySymbols() 和 Reflect.ownKeys() 取到。

在 ES5 使用字符串表示常量。但是用字符串不能保證常量是獨特的,這樣會引起一些問題,比如多個變常量都爲同一個值。但是使用 Symbol 定義常量,這樣就可以保證這一組常量的值都不相等。Symbol 的值是唯一的,所以不會出現相同值得常量,即可以保證 switch 按照代碼預想的方式執行。
這裏看教程的例子不太能理解,所以自己嘗試運行和改動一些地方看看結果:

const COLOR_RED = "red";
const COLOR_YELLOW = "yellow";
const COLOR_BLUE = "blue";
const MY_BLUE = "blue";

function getConstantName(color) {
  switch (color) {
    case COLOR_RED:
      return "COLOR_RED";
    case COLOR_YELLOW:
      return "COLOR_YELLOW ";
    case COLOR_BLUE:
      return "COLOR_BLUE";
    case MY_BLUE:
      return "MY_BLUE";
    default:
      throw new Exception("Can't find this color");
    }
}

console.log(getConstantName(COLOR_BLUE))
console.log(getConstantName(MY_BLUE))

上面的代碼輸出:
COLOR_BLUE
COLOR_BLUE
這是因爲COLOR_BLUE和MY_BLUE相等,都爲"blue"

const COLOR_RED = Symbol("red");
const COLOR_YELLOW = Symbol("yellow");
const COLOR_BLUE = Symbol("blue");
const MY_BLUE = Symbol("blue");

function getConstantName(color) {
  switch (color) {
    case COLOR_RED:
      return "COLOR_RED";
    case COLOR_YELLOW:
      return "COLOR_YELLOW ";
    case COLOR_BLUE:
      return "COLOR_BLUE";
    case MY_BLUE:
      return "MY_BLUE";
    default:
      throw new Exception("Can't find this color");
  }
}

console.log(getConstantName(COLOR_BLUE))
console.log(getConstantName(MY_BLUE))

上面的代碼輸出:
COLOR_BLUE
MY_BLUE
這是因爲COLOR_BLUE和MY_BLUE不相等,即Symbol(“blue”)與Symbol(“blue”)不相等

Symbol.for()
Symbol.for() 類似單例模式,首先會在全局搜索被登記的 Symbol 中是否有該字符串參數作爲名稱的 Symbol 值,如果有即返回該 Symbol 值,若沒有則新建並返回一個以該字符串參數爲名稱的 Symbol 值,並登記在全局環境中供搜索。

Symbol.keyFor()
Symbol.keyFor() 返回一個已登記的 Symbol 類型值的 key ,用來檢測該字符串參數作爲名稱的 Symbol 值是否已被登記。
教程中的代碼yellow === yellow1爲false的原因是第一行並沒有登記"Yellow",必須用Symbol.for()才能登記

let yellow = Symbol("Yellow");
let yellow1 = Symbol.for("Yellow");
yellow === yellow1;      // false
 
let yellow2 = Symbol.for("Yellow");
yellow1 === yellow2;     // true

用Symbol.keyFor()即可判斷登記情況:

let yellow = Symbol("Yellow");
console.log(Symbol.keyFor(yellow));
let yellow1 = Symbol.for("Yellow");  
console.log(Symbol.keyFor(yellow1));  

上面代碼輸出:
undefined
Yellow
登記成功後,用Symbol.for()得到的值都是一樣的,所以yellow1 === yellow2爲true,這是跟Symbol()不同的地方。
個人理解是Symbol()就像每個人雖然有的人名字一樣,但都是不同的人,而Symbol.for()只要第一個人第一次登記後,後面別人再用都是在用第一個人所登記的,比如公共庫,網站名稱(不一定準確)等。

更詳細準確的用法可以參考官方文檔:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Symbol/for
和阮一峯的開源教程書籍:http://es6.ruanyifeng.com/#docs/symbol

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章