1. 程式人生 > >探祕JS的所謂的第七種資料型別Symbol

探祕JS的所謂的第七種資料型別Symbol

首先,為什麼說叫所謂呢?
       因為在2007年之前Js給予我們typeof解析資料型別的一共有六種(一直有爭議,但是我們暫時就按typeof來算)
       'function'
       'Number' 
       'Object'
       'boolean'
       'String' 
       'undefined'
       當我們去 typeof Symbol()的時候會驚奇的發現 返回了一個‘symbol’ ;
    

       首先肯定要有疑問,這貨是啥?當然第一種想法其實就是肯定很強大。因為前六種已經強大的一種地步了,這貨肯定也一定非常強大。
       首先我們先帶著我們的好奇心一步一步來看看這個鬼東西...

       首先先驗證一下它是不是物件。
       通過我先說一下我對物件研究的他有三種機制:
       1.只要是物件就可以引用。
       2.只要是物件都可以賦予私有屬性。
       3.物件都不相等。


       那麼
       var a = Symbol();
       a.b = 10;//賦予私有屬性
       a.b // undefined 
       那麼看來這貨不是個物件 ,既然不是物件我們來看看它的一些別的特性.

       首先在api上Symbol提供了兩個方法第一個是for 另外一個是keyFor


        var s1 = Symbol.for('abc');
        var s2 = Symbol.for('abc'); 
        Symbol() === Symbol() //false 
        s1 === s2    //true 

       Symbol.keyFor(s1)// 'abc'

       當然這兩個看起來比較容易 似乎就是一個賦予一個值然後就會把原來的值吐出來,當然真是原來的值麼?帶著這樣的疑問我又繼續做了一些實驗。
        var s1 = Symbol.for([1,2,3]);
        Symbol.keyFor(s1); //  "1,2,3" 字串的 1,2,3

        var s1 = Symbol.for(function (){});
       Symbol.keyFor(s1); "function (){}"   字串的fn;
      
       你會發現這貨你存的東西只會以字串的東西吐出來。 
       當然這個東西官方說由於每一個Symbol值都是不相等的,這意味著Symbol值可以作為識別符號,用於物件的屬性名,就能保證不會出現同名的屬性。這對於一個物件由多個模組構成的情況非常有用,能防止某一個鍵被不小心改寫或覆蓋。 
       也就是說可以作為存在json 中讓key 永遠不相等.ok,那麼就完全可以這樣..
       var a = {};
       a[Symbol()]= 'Hello!';
       a[Symbol()]= 'Hello!';
       a[Symbol()]= 'Hello!'; 
      console.log(a);

      Object
          Symbol(): "Hello!"
          Symbol(): "Hello!"
          Symbol(): "Hello!"
      __proto__: Object 
     你會發現出現了連續的三個 a的屬性 都是hello 並且沒有覆蓋 。也就是說這麼寫的話可以有效的防止其json重名問題,不過拿起來就非常費勁了.
      for(var i in a){
           console.log(i +',' +a) //沒有任何的東西 
      }      
      當然這就比較可以可疑了 json 用symbol 存上東西了 但是又用for in 拿不到 也就說如果直接這麼賦值 json認但是for in 迴圈不認.而且咱們也拿不到。
      但是換一種方式就沒問題了。用變數存的話,雖然雖然for in 拿不到 但是咱們可以拿到值。
      var a = Symbol('aaa');
      b = {};
      b[a] = 10 ;
      console.log(b[a])//10 輕鬆拿到值
      其實不難看出來 Symbol對for in不是很友好,但是 對json 很友好。 
      
      這時如果使用別的方法拿值呢?顧名思義,Object.getOwnPropertyNames()是拿物件私有屬性的的方法。我們來試試。
      let b = {};
      b[Symbol()]=10;
      b[Symbol()]=15;
      Object. getOwnPropertyNames(b) //[] 可以理解為 其實 Symbol不作為b的私有屬性存在。
      當然能不能拿到呢?其實也能拿到。
      他提供了一個getOwnPropertySymbols方法可以讓我找到存在記憶體裡的Symbol;
      例如:
      let a = {};
      a[Symbol()]=10;
      a[Symbol()]=15;
      Object.getOwnPropertySymbols(a) //[Symbol(),Symbol()] //這裡面以陣列的形式返回了 咱們使用的兩個Symbol();
      Object.getOwnPropertySymbols(a)[0]//Symbol() 第一個Symbol()
      a[Object.getOwnPropertySymbols(a)[0]]//10 拿到存在的這個值。
      其實知道是陣列後 我們就可以迴圈 obj.getOwnPropertySymbols(a) 這個東西 然後輸出值了。其實說回來只是換了一種方法拿值,存值。而這種方法更安全更隱蔽而已。


     而Symbol還有一些比較特殊的特性。
     js中的~(按位非) 是一個比較強勢的轉換number的東西。例如:
     ~NaN  //-1
     ~function (){}//-1
     ~undefined   //-1
     var a = function (){};
     ~a()  //-1
     ~new a() //-1
     基本任何東西都能轉成number,而
     ~Symbol //-1
     ~Symbol() //報錯  似乎說明了 其跟function 有著本質的區別;

      另外呢,Symbol值不能與其他型別的值進行運算,會報錯。


     var sym = Symbol('My symbol');


     "your symbol is " + sym     // TypeError: can't convert symbol to string   es5之前的報錯
     `your symbol is ${sym}`     // TypeError: can't convert symbol to string   es6字串照樣的報錯


    另外,Symbol值也可以轉為布林值,但是不能轉為數值。


    var sym = Symbol();
    Boolean(sym) // true
    !sym  // false


    Number(sym) // TypeError
    sym + 2 // TypeError 

    這些都是Symbol的一些小特性。 


     其實來說Symbol作為一個新的資料型別 最強的而不是幹以上的這些事而是一些配合原型方法的一些開關,可以強化方法的使用。
     比如說 Symbol.isConcatSpreadable 這個方法
      咱們都知道 正常的陣列concat方法是連線字串 。
     let arr = ['c', 'd'];
     ['a', 'b'].concat(arr2,'e') //['a','b','c','d','e'];
     而我們一旦把開關開啟後會發現一些意想不到的結果;
     let arr2 = ['c', 'd'];
     arr2[Symbol.isConcatSpreadable] = false;
     ['a', 'b'].concat(arr2, 'e') //['a','b',['c','d'],'e']//會發現以陣列的形式插入到裡面了。

    當然他還包括了一些別的方法例如 他可以測試ES6 新增的內建物件方法 Symbol.toStringTag。

    JSON[Symbol.toStringTag]:'JSON'
    Math[Symbol.toStringTag]:'Math'
    Module物件M[Symbol.toStringTag]:'Module'
    ArrayBuffer.prototype[Symbol.toStringTag]:'ArrayBuffer'  
    DataView.prototype[Symbol.toStringTag]:'DataView'
    Map.prototype[Symbol.toStringTag]:'Map'
    Promise.prototype[Symbol.toStringTag]:'Promise'
    Set.prototype[Symbol.toStringTag]:'Set'
    %TypedArray%.prototype[Symbol.toStringTag]:'Uint8Array'等
    WeakMap.prototype[Symbol.toStringTag]:'WeakMap'
    WeakSet.prototype[Symbol.toStringTag]:'WeakSet'
    %MapIteratorPrototype%[Symbol.toStringTag]:'Map Iterator'
    %SetIteratorPrototype%[Symbol.toStringTag]:'Set Iterator'
    %StringIteratorPrototype%[Symbol.toStringTag]:'String Iterator'
    Symbol.prototype[Symbol.toStringTag]:'Symbol'
    Generator.prototype[Symbol.toStringTag]:'Generator'
    GeneratorFunction.prototype[Symbol.toStringTag]:'GeneratorFunction' 

     不過其實用ES5之前的方法依然也可以檢驗出來內建物件,所以Symbol就是更規範化而已,就用map舉例:
     Object.prototype.toString.call(new Map())//'[object Map]'
     
     別的內建物件也是同理。

    Symbol.unscopables 也是Symbol一個比較有意思的東西。可以找到物件內哪些屬性被with排除。
   Object.keys(Array.prototype[Symbol.unscopables])//['copyWithin', 'entries', 'fill', 'find', 'findIndex', 'keys'] 以陣列的形式返回 也就是說 這些屬性會被with排除。
    
     其實這些只是Smybol的冰山一角,更多的是Symbol是服務於ES6中。
     讓我們繼續慢慢探索好了。

相關推薦

探祕JS所謂資料型別Symbol

首先,為什麼說叫所謂呢?        因為在2007年之前Js給予我們typeof解析資料型別的一共有六種(一直有爭議,但是我們暫時就按typeof來算)        'function'        'Number'         'Object'       

javascript資料型別Symbol

Symbol 是什麼? Symbols 不是圖示,也不是指在程式碼中可以使用小圖片: 也不是指代其他一些東西的語法。那麼,Symbol 到究竟是什麼呢? 七種資料型別 JavaScript 在 1997 年被標準化時,就有 6 種資料型

JavaScript中資料型別·中·一

Standing on Shoulders of Giants; 說到JavaScript裡的型別很容易就讓人想起 42和"42",分別是string型和number型,但是他們可以直接進行運算。這就是Js裡面有趣又讓人頭疼的問題了。JavaScript會進行==強制型別轉換== 下面我們就正式

String資料型別轉換成long、int、double、float、boolean、char等資料型別

String C="true"; //當String型別資料值為true/false時,直接輸出true/false boolean N=Boolean.parseBoolean(+C); System.out.println("String型別轉換成boolean型別:"N); //當String型別資料

面試中經常問到的Redis資料型別,你都真正瞭解嗎?

前言 Redis不是一個簡單的鍵值對儲存,它實際上是一個支援各種型別資料結構的儲存。在傳統的鍵值儲存中,是將字串鍵關聯到字串值,但是在Redis中,這些值不僅限於簡單的字串,還可以支援更復雜的資料結構。下面就是Redis支援的資料結構: 字串(String):二進位制安全字串。 列表(List):根據插入順

開啟運維之路之 6 篇——Redis五資料型別string、list、hash、set、zset

1、上一篇介紹Redis的基礎,提供2種啟動方式,這裡彙總一下: ①寫 shell 指令碼,執行 shell 指令碼。詳見上一篇文章結尾。 ②[[email protected] ~]# cd /usr/local/redis/ [[email protected

JS資料型別轉換(最全)

一、轉為字串:使用 .toString或者String。 1、 .toString()方法:注意,不可以轉null和underfined //轉為字串-->toString方法 var bool=true; console.log(bool.toString()); //注意,toSt

JS的幾資料型別

在JavaScript中,一共有六種資料型別,如下圖所示: 一、數字型別(Number) 1、最基本的資料型別; 2、不區分整型數值和浮點型數值; 3、能表示的最大值是±1.7976931348623157乘以10的308次方;能表示的最小值是±5 乘以10的-324次方; 4、包含十

JS的5資料型別及其與Boolean的轉換規則

資料型別 轉化為 true 值 轉化為 false 值 Boolean true false String

JS中六資料型別(一)——Undefined

轉載自:http://blog.csdn.net/a2296096931/article/details/51072448 侵刪 JS中有6種資料型別:Undefined、Null、Boolean、Number、String和Object。JS中不支援任何建立自定義型別

JS中六資料型別(五)——String

    String型別用於表示由零或多個16位Unicode字元組成的字元序列,即字串。字串可以由雙引號(“)或單引號(‘)表示,因此下面兩種字串的寫法都是有效的:     var firstNam

JS中六資料型別(六)——Object

ECMAScript中的物件是可變的鍵控集合(即一組資料和功能的集合)。它將很多值聚合在一起,可通過名字訪問這些值。物件也可看做屬性的容器,每個屬性都是一個名/值對。屬性的名字可以是包括空字串在內的任

JS中六資料型別(四)——Number

     Number型別應該是ECMAScript中最令人關注的資料型別了,這種型別使用IEEE754格式來表示整數和浮點數值(浮點數值在某些語言中也被稱為雙精度數值)。為支援各種數值型別,EC

redis學習 三章 5資料型別----String型別

跟著Redis入門指南學習 第三章 5種資料型別 3.1 熱身 先了解幾個比較基礎的命令作為熱身,開啟redis-cli,跟著樣例輸入命令來體驗下: 1.獲取符合規範的健名列表 keys patternpattern支援glob風格萬用字元格式,具體規則如下: 符號 含

Redis-五章節-8資料型別

# 目錄 - 一、Redis對key的操作 - 二、五種資料型別 - String型別 - List(集合) - Set(集合) - Hash(雜湊) - Zset(有序集合) - 三、三種特殊資料型別 - geospatial(地理位置) - hyperloglog(優點:佔用記

JavaScript兩資料型別的儲存方式

JavaScript中資料型別的儲存 區別: 兩種型別的區別是:儲存位置不同 基本資料型別 原始資料型別是直接儲存在棧(stack)中的簡單資料段。因為佔據空間小、大小固定,屬於被頻繁使用資料,所以放入棧中儲存。 引用資料型別 引用資料型別儲存在堆(heap)中的物件,佔據空間大、大小不固定。如果

Java 8 資料型別 位元組大小

原文出處 部落格地址 http://blog.csdn.net/never_cxb https://blog.csdn.net/never_cxb/article/details/47204485 型別 大小 int 4個位元

C語言三天-資料型別,if switch,for while

背會!!! 格式字元有d,o,x,u,c,s,f,e,g等。  如 %d整型輸出,%ld長整型輸出, %o以八進位制數形式輸出整數, %x以十六進位制數形式輸出整數,或輸出字串的地址。 %u以十進位制數輸出unsigned型資料(無符號數)。注意:%d與%u有無符號的數

Redis 常用的五資料型別和操作

第一部分:五種型別的基礎操作 (文章分為兩部分,基礎操作和詳細操作)   一、Redis 字串(String) Redis 字串資料型別的相關命令用於管理 redis 字串值,基本語法如下: 語法 redis 127.0.0.1:6379> COMMAND K

第一模組-:(2章)資料型別、字元編碼、檔案操作

1、漢字點陣碼是一種用黑白兩色點陣來表示漢字字形的編碼。一個8*8點陣字模的儲存容量為? 1、1位元組(Byte)有8位元(Bit) 2、黑白兩色每個點佔用1Bit 3、8×8點陣需要64個Bit 4、因為1Byte有8Bit,所以64Bit/8Bit/Byte = 8Byte 答案是B:8位