文章出處

  本文所有Demo的運行環境都為nodeJS, 參考:讓nodeJS支持ES6的詞法----babel的安裝和使用 

  ES6新增了一種數據類型:SymbolSymbol是用來定義對象的唯一屬性名的不二之選;

  Symbol如何使用

  Symbol如何使用呢, Symbol不是一個構造函數哦, 如果用new Symbol的話, 會報錯的:

var sym1 = Symbol();
var sym2 = Symbol("foo");
var sym3 = Symbol("foo");
console.log(sym1, sym2, sym3) //輸出Symbol() Symbol(foo) Symbol(foo)

  連自己都不等于自己

//用同樣的參數創建兩次, 也是不相等的:
Symbol("foo") === Symbol("foo"); //輸出:false

  作為屬性名的Symbol;使用Symbol給對象添加唯一的屬性, Symbol也能作為對象的函數名;

let obj = {};
let sAttr0 = Symbol("hehe");
let sAttr1 = Symbol("meme");
obj[sAttr1] = 1;
console.log(obj[sAttr1]);

obj[sAttr0] = () => {
    return ++obj[sAttr0];;
};

  我們可以用typeof判斷某一個變量類型為Symbol類型:

typeof Symbol() === 'symbol' //輸出:true
typeof Symbol('foo') === 'symbol' //輸出: true
typeof Symbol.iterator === 'symbol' //輸出 : true

  如果我們不知道Symbol的實例名字是什么,我們怎么獲取到Symbol值的呢, Symbol無法被for infor of循環,以及Object.keys, Object.values 等都無法遍歷到Symbol的屬性; Object下給我們提供了一個getOwnPropertySymbols

let sym0 = Symbol("o_o?");
let obj = {
    [sym0] : "heheda"
}
for( let prop of Object.getOwnPropertySymbols(obj) ) {
    //prop就是Symbol的名字
    console.log( obj[prop] ); //輸出:heheda
};

  或者用ES6提供的反射 : Reflect.ownKeys, 反射?

let sym0 = Symbol("o_o?");
let obj = {
    [sym0] : "heheda"
}
console.log( Reflect.ownKeys(obj) ); //輸出:[ Symbol(o_o?) ]

   Symbol.for和 Symbol.keyFor

  Symbol.for和Symbol的唯一區別是 Symbol.for創建的兩個實例可能相等, 根據Symbol的參數生成實例, 如果參數一樣, 那么會返回同一個實例;

let foo = Symbol.for( "1111" );
let bar = Symbol.for("1111");
console.log( foo === bar );  //輸出: true
//只有通過Symbol.for創建的對象,才能用keyFor找到原來的參數;
console.log(Symbol.keyFor(foo)) //會輸出:1111

  

  Symbol的屬性以及這些屬性的用處:

  Symbol.prototype: Symbol有指向的原型:

console.log(Symbol.prototype); //輸出Symbol的原型

  Symbol.length: Symbol的length為1, 也就是說調用Symbol需要一個參數, 當然不給參數也沒啥事。

  Symbol.Iterator:對象的Symbol.Iterator屬性, 指向這個對象的默認遍歷器:

var myIterable = {};
myIterable[Symbol.iterator] = function* () {
    yield 1;
    yield 2;
    yield 3;
};
console.log([...myIterable]); // [1, 2, 3]

  Symbol.match:ES6中字符串去匹配對象的Symbol.match方法, 匹配的結果完全可控, 以下Demo,相當于把字符串"strstring"作為obj[Symbol.match]方法的參數, 然后返回用戶設定的值, chrome和FF目前還不支持:

let obj = {
    [Symbol.match](string) {
        console.log(string);
        return "heheda";
    }
};;
console.log("strstring".match(obj));

    

  Symbol.replace:和上面的道理一樣:

let obj = {
    [Symbol.replace](string) {
        console.log(string);
        return "replllll";
    }
};
console.log( "sssss".replace(obj) ); //輸出:  sssss    replllll

  Symbol.split:和上面的道理一樣。

  Symbol.toPrimitive:對象的Symbol.toPrimitive指向一個方法, 當對象轉化為原始值得話, 會調用這個方法, 一個對象轉為原始值由三種情況:string, number, default

    var obj1 = {};
    console.log(+obj1);     // NaN
    console.log(`${obj1}`); // "[object Object]"
    console.log(obj1 + ""); // "[object Object]"

    // obj2有定義Symbol.toPrimitive屬性;
    var obj2 = {
        [Symbol.toPrimitive](hint) {
        if (hint == "number") {
            return 10;
        }
        if (hint == "string") {
            return "hello";
        }
        return true;
    }
    };
    console.log(+obj2);     // 10      -- 轉化 為 "number"
    console.log(`${obj2}`); // "hello" -- 轉化 為 "string"
    console.log(obj2 + ""); // "true"  -- 轉化 為 "default"

  Symbol.toStringTag:Symbol.toStringTag, 這個玩意兒厲害了, 連對象的toString方法都給改了,而且用Object.prototype.toString.call這個對象 輸出也是一樣的, 這個情何以堪, 以后判斷元素類型必須用別的方法了, 改動大了.... :

console.log({ [Symbol.toStringTag] : "str "}.toString()); //輸出:[object str ]
console.log(Object.prototype.toString.call({ [Symbol.toStringTag] : "str "}))
//輸出:[object str ]
class Collection { get [Symbol.toStringTag]() { return 'xxx'; } } var x = new Collection(); console.log(x.toString())// 輸出:"[object xxx]"

   參考:

    mdn:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol

    阮一峰ECMAScript 6 入門:http://es6.ruanyifeng.com/#docs/symbol

作者: NONO
出處:http://www.cnblogs.com/diligenceday/
QQ:287101329
微信:18101055830 


文章列表


不含病毒。www.avast.com
arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()