摘要:前端技術日新月異,不斷有新技術出現,我們就需要不斷地學習新知識,雖然已經提出很久了,但是最近我才有時間靜下心來好好學習一下里面提出的新規則。
前端技術日新月異,不斷有新技術出現,我們就需要不斷地學習新知識,雖然ES6已經提出很久了,但是最近我才有時間靜下心來好好學習一下里面提出的新規則。今天總結下ES6提出的這個新的原始數據類型--Symbol。
為啥需要Symbol一個新規則的提出,必然是因為有需求,熟悉ES5的人都知道,ES5里面對象的屬性名都是字符串,如果你需要使用一個別人提供的對象,你對這個對象有哪些屬性也不是很清楚,但又想為這個對象新增一些屬性,那么你新增的屬性名就很可能和原來的屬性名發送沖突,顯然我們是不希望這種情況發生的。所以,我們需要確保每個屬性名都是獨一無二的,這樣就可以防止屬性名的沖突了。因此,ES6里就引入了Symbol,用它來產生一個獨一無二的值。
Symbol是什么我們已經知道ES6中引入了一個叫Symbol的東西,但是這個東西到底是什么呢?是一個函數還是一個對象或者是其他什么?Symbol實際上是ES6引入的一種原始數據類型,除了Symbol,JavaScript還有其他5種數據類型,分別是Undefined、Null、Boolean、String、Number、對象,這5種數據類型都是ES5中就有的。
怎么生成一個Symbol類型的值既然我們已經知道了Symbol是一種原始的數據類型,那么怎么生成這種數據類型的值呢?Symbol值是通過Symbol函數生成的,如下:
let s = Symbol(); console.log(s); // Symbol() typeof s; // "symbol"
上面代碼中,s就是一個Symbol類型的值,它是獨一無二的。
Symbol函數前不能用newSymbol函數不是一個構造函數,前面不能用new操作符。所以Symbol類型的值也不是一個對象,不能添加任何屬性,它只是一個類似于字符型的數據類型。如果強行在Symbol函數前加上new操作符,會報錯,如下:
let s = new Symbol(); // Uncaught TypeError: Symbol is not a constructor(…)Symbol函數的參數 字符串作為參數
用上面的方法生成的Symbol值不好進行區分,Symbol函數還可以接受一個字符串參數,來對產生的Symbol值進行描述,方便我們區分不同的Symbol值。
let s1 = Symbol("s1"); let s2 = Symbol("s2"); console.log(s1); // Symbol(s1) console.log(s2); // Symbol(s2) s1 === s2; // false let s3 = Symbol("s2"); s2 === s3; // false
從上面代碼可以看出:
給Symbol函數加了參數之后,控制臺輸出的時候可以區分到底是哪一個值;
Symbol函數的參數只是對當前Symbol值的描述,因此相同參數的Symbol函數返回值是不相等的;
對象作為參數如果Symbol函數的參數是一個對象,就會調用該對象的toString方法,將其轉化為一個字符串,然后才生成一個Symbol值。所以,說到底,Symbol函數的參數只能是字符串。
Symbol值可以進行運算么?既然Symbol是一種數據類型,那我們一定想知道Symbol值是否能進行運算。告訴你,Symbol值是不能進行運算的,不僅不能和Symbol值進行運算,也不能和其他類型的值進行運算,否則會報錯。
Symbol值可以顯式轉化為字符串和布爾值,但是不能轉為數值。
var mysym1 = Symbol("my symbol"); mysym1.toString() // "Symbol("my symbol")" String(mysym1) // "Symbol("my symbol")" var mysym2 = Symbol(); Boolean(mysym2); // true Number(mysym2) // TypeError: Cannot convert a Symbol value to a number(…)Symbol如何作為屬性名
Symbol就是為對象的屬性名而生,那么Symbol值怎么作為對象的屬性名呢?有下面幾種寫法:
let a = {}; let s4 = Symbol(); // 第一種寫法 a[s4] = "mySymbol"; // 第二種寫法 a = { [s4]: "mySymbol" } // 第三種寫法 Object.defineProperty(a, s4, {value: "mySymbol"}); a.s4; // undefined a.s4 = "mySymbol"; a[s4] // undefined a["s4"] // "mySymbol"
從上面代碼可以看出:
使用對象的Symbol值作為屬性名時,獲取相應的屬性值不能用點運算符;
如果用點運算符來給對象的屬性賦Symbol類型的值,實際上屬性名會變成一個字符串,而不是一個Symbol值;
在對象內部,使用Symbol值定義屬性時,Symbol值必須放在方括號之中,否則只是一個字符串。
Symbol值作為屬性名的遍歷使用for...in和for...of都無法遍歷到Symbol值的屬性,Symbol值作為對象的屬性名,也無法通過Object.keys()、Object.getOwnPropertyNames()來獲取了。但是,不同擔心,這種平常的需求肯定是會有解決辦法的。我們可以使用Object.getOwnPropertySymbols()方法獲取一個對象上的Symbol屬性名。也可以使用Reflect.ownKeys()返回所有類型的屬性名,包括常規屬性名和 Symbol屬性名。
let s5 = Symbol("s5"); let s6 = Symbol("s6"); let a = { [s5]: "s5", [s6]: "s6" } Object.getOwnPropertySymbols(a); // [Symbol(s5), Symbol(s6)] a.hello = "hello"; Reflect.ownKeys(a); // ["hello", Symbol(s5), Symbol(s6)]
利用Symbol值作為對象屬性的名稱時,不會被常規方法遍歷到這一特性,可以為對象定義一些非私有的但是又希望只有內部可用的方法。
Symbol.for()和Symbol.keyFor()Symbol.for()函數也可以用來生成Symbol值,但該函數有一個特殊的用處,就是可以重復使用一個Symbol值。
let s7 = Symbol.for("s7"); console.log(s7); // Symbol(s7) s7.toString(); // "Symbol(s7)" let s8 = Symbol.for("s8"); s7 === s8 // true let s9 = Symbol(); Symbol.keyFor(s9); // undefined Symbol.keyFor(s8); // "s8"
Symbol.for()函數要接受一個字符串作為參數,先搜索有沒有以該參數作為名稱的Symbol值,如果有,就直接返回這個Symbol值,否則就新建并返回一個以該字符串為名稱的Symbol值。上面代碼中,s7和s8實際上就是同一個Symbol值,所以兩者是相等的。
Symbol.keyFor()函數是用來查找一個Symbol值的登記信息的,Symbol()寫法沒有登記機制,所以返回undefined;而Symbol.for()函數會將生成的Symbol值登記在全局環境中,所以Symbol.keyFor()函數可以查找到用Symbol.for()函數生成的Symbol值。
ES6提供了11個內置的Symbol值,分別是Symbol.hasInstance 、Symbol.isConcatSpreadable 、Symbol.species 、Symbol.match 、Symbol.replace 、Symbol.search 、Symbol.split 、Symbol.iterator 、Symbol.toPrimitive 、Symbol.toStringTag 、Symbol.unscopables 等。
有興趣的可以自行了解:http://es6.ruanyifeng.com/#docs/symbol
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/91273.html
摘要:靜態方法靜態方法直接用類名來調用就可以了,熟悉面向對象編程的同學應該都不陌生。在中,一個類不能繼承多個類。為了解決這個問題,可以使用。當類表達式有命名時,該命名僅作為類內部使用。 本文同步自我得博客:http://www.joeray61.com 簡介 ES6的Classes是在原型鏈繼承的基礎上,由語言本身提供的語法糖,并非是一種全新的繼承模式。這使得Javascript有一種更加簡...
摘要:的碼點被稱為基本字符區域。關于的介紹,我準備用文檔阮一峰來做一些介紹,具體的可以參考文檔引入的原因的對象屬性名都是字符串,這容易造成屬性名的沖突。其他的一些屬性可以去看文檔阮一峰注意函數前不能使用命令,否則會報錯。 筆記說明 重學前端是程劭非(winter)【前手機淘寶前端負責人】在極客時間開的一個專欄,每天10分鐘,重構你的前端知識體系,筆者主要整理學習過程的一些要點筆記以及感悟,完...
摘要:的碼點被稱為基本字符區域。關于的介紹,我準備用文檔阮一峰來做一些介紹,具體的可以參考文檔引入的原因的對象屬性名都是字符串,這容易造成屬性名的沖突。其他的一些屬性可以去看文檔阮一峰注意函數前不能使用命令,否則會報錯。 筆記說明 重學前端是程劭非(winter)【前手機淘寶前端負責人】在極客時間開的一個專欄,每天10分鐘,重構你的前端知識體系,筆者主要整理學習過程的一些要點筆記以及感悟,完...
摘要:的碼點被稱為基本字符區域。關于的介紹,我準備用文檔阮一峰來做一些介紹,具體的可以參考文檔引入的原因的對象屬性名都是字符串,這容易造成屬性名的沖突。其他的一些屬性可以去看文檔阮一峰注意函數前不能使用命令,否則會報錯。 筆記說明 重學前端是程劭非(winter)【前手機淘寶前端負責人】在極客時間開的一個專欄,每天10分鐘,重構你的前端知識體系,筆者主要整理學習過程的一些要點筆記以及感悟,完...
閱讀 3328·2023-04-26 00:07
閱讀 3922·2021-11-23 10:08
閱讀 2940·2021-11-22 09:34
閱讀 859·2021-09-22 15:27
閱讀 1749·2019-08-30 15:54
閱讀 3743·2019-08-30 14:07
閱讀 913·2019-08-30 11:12
閱讀 678·2019-08-29 18:44