您的位置:首页 > Web前端 > JavaScript

理解ES6中的Symbol (understanding es6 第5章)

2018-03-06 19:28 387 查看
英文电子书点此阅读《understanding es6》

目录

symbol 和 symbol属性
创建symbols

使用Symbols

共享Symbols
Symbol Coercion 类型强制转换

检索对象的symbol

用 well-known Symbols 暴露内部操作(似乎没什么用)

summary

symbol 和 symbol属性

一开始出于对象属性的私有性的考虑,在基础数据类型中添加了symbol(string, number, boolean, null, undefined)。但后来真正改变的只是key值不再仅仅是字符串了,私有性的初衷被放弃了。

创建symbols

symbol 没有字面量的形式。要用全局的 Symbol() 函数来创建。

由于它属于基本变量,也不能 new 一个 。

Symbol 函数可以接受一个可选的参数作为其描述。这个描述不能用于获取对象的属性,只是debug有用。

let firstName = Symbol()
let secondName = Symbol('lala')

let person = {}
person[secondName] = 'wuwuwuwu'


使用Symbols

用法同computed property name

let firstName = Symbol("first name");

// use a computed object literal property
let person = {
[firstName]: "Nicholas"
};

// make the property read only
Object.defineProperty(person, firstName, { writable: false });


共享Symbols

如果想要创建一个共享的symbol,用 Symbol.for() 方法,而不是 Symbol() 方法

Symbol.for()接收一个参数,作为该symbol的字符标识符,同时也是symbol的描述

// 首先它会全局搜索是否有这样一个key 叫 "uid" 的 symbol, 如果有就返回这个symbol。
// 如果没有,会创建一个新的symbol,并且注册到全局的symbol 体系中。并返回这个新symbol。

let uid = Symbol('uid')
let object = {}

object[uid] = 12345

console.log(object[uid]);       // 12345
console.log(uid);               // "Symbol(uid)"

let uid2 = Symbol.for("uid");

console.log(uid === uid2);      // true

Symbol.keyFor(uid2);     // "uid"
//如果不用 Symbol.for来创建symbol, 那全局的symbol中就没有它,用keyfor寻找会找不到。


Symbol Coercion 类型强制转换

symbol 不能被随意转换为string/number。除非显式转换。

symbol 被转为 布尔型数据时, 都是true

var uid = Symbol.for('uid')

var des = String(uid)
//"Symbol(uid)"

des = uid + ''
//VM1517:1 Uncaught TypeError: Cannot convert a Symbol value to a string

des = +uid
//VM1520:1 Uncaught TypeError: Cannot convert a Symbol value to a number


检索对象的symbol

之前的 Object.keys()/Object.getOwnPropertyNames() 都拿到不到symbol

ES6新加了 Object.getOwnPropertySymbols()方法来以数组的方式收集对象的自有symbols

let uid = Symbol.for("uid");
let object = {
[uid]: "12345"
};

let symbols = Object.getOwnPropertySymbols(object);


用 well-known Symbols 暴露内部操作(似乎没什么用)

这些 well-known Symbols 的 descriptor 就是类似 “Symbol.hasInstance” 这样的,同时也被定义在了 Global 的 Symbol 体系上。

Symbol.hasInstance 定义在 Fuction.prototype 上

Object.getOwnPropertySymbols(Function.prototype)  //[Symbol(Symbol.hasInstance)]

obj instanceof Array
// 就等于 用 Array 的 symbol 属性来取得其值
Array[Symbol.hasInstance](obj)


也可以改写该函数,但必须用Object.defineProperty() 方法

function SpecialNumber() {
// empty
}

Object.defineProperty(SpecialNumber, Symbol.hasInstance, {
value: function(v) {
return (v instanceof Number) && (v >=1 && v <= 100);
}
});

let two = new Number(2),
zero = 0;

console.log(two instanceof SpecialNumber);    // true
console.log(zero instanceof SpecialNumber);   // false

注意instanceof 的左侧必须是一个显式声明的对象,从而来调用instanceof,因为非对象只会简单地返回一个 false


4000
后面的东西太细节了,用的时候去看api吧。

放点代码:

// effectively equivalent to /^.{10}$/
let hasLengthOf10 = {
[Symbol.match]: function(value) {
return value.length === 10 ? [value] : null;
},
[Symbol.replace]: function(value, replacement) {
return value.length === 10 ? replacement : value;
},
[Symbol.search]: function(value) {
return value.length === 10 ? 0 : -1;
},
[Symbol.split]: function(value) {
return value.length === 10 ? ["", ""] : [value];
}
};

let message1 = "Hello world",   // 11 characters
message2 = "Hello John";    // 10 characters

let match1 = message1.match(hasLengthOf10),
match2 = message2.match(hasLengthOf10);

console.log(match1);            // null
console.log(match2);            // ["Hello John"]

let replace1 = message1.replace(hasLengthOf10, "Howdy!"),
replace2 = message2.replace(hasLengthOf10, "Howdy!");

console.log(replace1);          // "Hello world"
console.log(replace2);          // "Howdy!"

let search1 = message1.search(hasLengthOf10),
search2 = message2.search(hasLengthOf10);

console.log(search1);           // -1
console.log(search2);           // 0

let split1 = message1.split(hasLengthOf10),
split2 = message2.split(hasLengthOf10);

console.log(split1);            // ["Hello world"]
console.log(split2);            // ["", ""]

function Temperature(degrees) {
this.degrees = degrees;
}

// hint 是被JS引擎自动赋给的
Temperature.prototype[Symbol.toPrimitive] = function(hint) {

switch (hint) {
case "string":
return this.degrees + "\u00b0"; // degrees symbol

case "number":
return this.degrees;

case "default":
return this.degrees + " degrees";
}
};

let freezing = new Temperature(32);

console.log(freezing + "!");            // "32 degrees!"
console.log(freezing / 2);              // 16
console.log(String(freezing));          // "32°"


判断是否是原生的json:

function supportsNativeJSON() {
return typeof JSON !== "undefined" &&
Object.prototype.toString.call(JSON) === "[object JSON]";
}


function Person(name) {
this.name = name;
}

Person.prototype[Symbol.toStringTag] = "Person";

let me = new Person("Nicholas");

console.log(me.toString());                         // "[object Person]"
console.log(Object.prototype.toString.call(me));    // "[object Person]"


summary

Symbols 是ES6新加的基本数据类型,只有用Symbol() 才能创建

虽然不是特别私有,但Symbol类型的 属性 更不容易被错误地删改

不能用 Object.keys() 或 Object.getOwnPropertyNames() 来获取symbol 属性,但可以用Object.getOwnPropertySymbols() 来检索symbol属性。

可以改写特殊的 well-known symbols,来自定义方法。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息