1. 基本用法

Symbol 是ES6引入的一种新的原始数据类型,表示独一无二的值。
前六种基础数据类型是 undefined null Boolean String Number Object
Symbol 值通过Symbol函数生成 可以接受一个字符串作为参数,主要为了区分不同Symbol值
参数若是一个对象,则会调用该对象的 toString 方法转成字符串 传递给Symbol
*** 参数只做为一个描述存在,同样的参数生成的Symbol也不相等
***** 不能用 new 创建
围绕原始数据类型创建一个显式包装器对象从 ECMAScript 6 开始不再被支持。然而,现有的原始包装器对象,如 new Boolean、new String以及new Number,因为遗留原因仍可被创建。
 let s1 = Symbol('foo');
let s2 = Symbol('bar');
let s3 = Symbol('bar');
console.log(s1); // Symbol(foo)
console.log(typeof s1); // symbol
console.log(String(s2)); // "Symbol(bar)" 不能用new String
console.log(Boolean(s2)); // true
console.log(Number(s2)); // 报错 TypeError: Cannot convert a Symbol value to a number
console.log(s2 === s3); //false
console.log(s3.description); //"bar" (ES2019)
 let obj1 = {
a: 12
};
let obj2 = {
a: 12,
toString() {}
};
let obj3 = {
a: 12,
toString() {
return this.a;
}
};
let s4 = Symbol(obj1);
let s5 = Symbol(obj2);
let s6 = Symbol(obj3);
console.log(s4); //Symbol([object Object])
console.log(s5); //Symbol(undefined)
console.log(s6); //Symbol(12)

2. 使用场景

基本应用场景有两种,一是作为key ,一是作为value
***作为key时 只能用 [] 定义 , 不能用 .
 let s7 = Symbol();
let s8 = Symbol();
let s9 = Symbol();
let jo = {
name: 'nan',
age: 18,
[s7]: 'Hi'
};
jo[s8] = 'hook';
Object.defineProperty(jo, s9, {
value: 'jay',
enumerable: true
})
console.log(jo); //{ name: 'nan', age: 18, [Symbol()]: 'Hi', [Symbol()]: 'hook', [Symbol()]: 'jay' }
console.log(jo[s8]); //hook
// 是无法通过正常的遍历方法取到Symbol 属性名的
// for...in / for...of / Object.keys() / Object.getOwnPropertyNames() / JSON.stringify()
// 可以通过 Object.getOwnPropertySymbols() / Reflect.ownKeys()
// 可以利用这个特点来定义一些不暴露出去的属性或方法
console.log(Object.keys(jo)); //[ 'name', 'age' ]
console.log(Object.getOwnPropertyNames(jo)); //[ 'name', 'age' ]
console.log(Object.getOwnPropertySymbols(jo)); //[ Symbol(), Symbol(), Symbol() ]
console.log(Reflect.ownKeys(jo)); //[ 'name', 'age', Symbol(), Symbol(), Symbol() ]
***作为value , 可以定义一组常量 , 并且保证这些常量的值不想等
当只想定义一组常量 , 并不关心值的时候 ,就可以使用Symbol来定义
 const PENDING = Symbol();
const SUCCESS = Symbol();
const FAIL = Symbol();
class Promise {
constructor (executor) {
this.state = PENDING;
let resolve = value => {
if (this.state === PENDING) {
this.state = SUCCESS;
// ...
}
}
let reject = reason => {
if (this.state === PENDING) {
this.state = FAIL;
// ...
}
}
executor(resolve, reject);
}
}

3. Symbol.for() & Symbol.keyFor()

Symbol.for() 接收一个字符串,然后搜索有没有以该参数作为名称的 Symbol 值, 有则直接返回,没有创建一个新的Symbol 且注册到全局 (可以应用到iframe中)
Symbol.keyFor 返回一个Symbol.for登记过值的 key
 let s10 = Symbol.for('foo');
let s11 = Symbol('foo');
console.log(Symbol.for('foo') === s10); //true
console.log(s11 === s10); //false
console.log(Symbol.keyFor(s10)); //"foo"
console.log(Symbol.keyFor(s11)); //undefined

4. 属性

1). Symbol.hasInstance 用于判断某对象是否为某构造器的实例。因此你可以用它自定义 instanceof 操作符在某个类上的行为。

 class Counts {
static [Symbol.hasInstance](instance) {
return !(instance % 2); //是否被 2 整除
}
}
console.log(1 instanceof Counts); //false
console.log(4 instanceof Counts); // true

2). Symbol.isConcatSpreadable 符号用于配置某对象作为Array.prototype.concat()方法的参数时是否展开其数组元素。

 let arr1 = [1, 2, 3];
let arr2 = ['a', 'b'];
console.log(arr1.concat(arr2)); //[ 1, 2, 3, 'a', 'b' ]
arr2[Symbol.isConcatSpreadable] = false;
console.log(arr1.concat(arr2)); //[ 1, 2, 3, ['a', 'b'] ]

3). Symbol.species 是个函数值属性,其被构造函数用以创建派生对象。

***你可能想在扩展数组类 MyArray 上返回 Array 对象。 例如,当使用例如 map() 这样的方法返回默认的构造函数时,你希望这些方法能够返回父级的 Array 对象,以取代 MyArray 对象。Symbol.species 允许你这么做:
 class MyArray extends Array {
// 覆盖 species 到父级的 Array 构造函数上
static get [Symbol.species]() { return Array; }
}
let a = new MyArray(1,2,3);
let mapped = a.map(x => x * x);
console.log(mapped instanceof MyArray); // false
console.log(mapped instanceof Array); // true

4). Symbol.iterator 为每一个对象定义了默认的迭代器。该迭代器可以被 for...of 循环使用。

 let myIterable = {}
myIterable[Symbol.iterator] = function* () {
let i = 0;
while (i < 5) {
yield i;
i++;
}
};
console.log([...myIterable]); //[ 0, 1, 2, 3, 4 ]
function getOdd () {
let arr = [];
for (let i of myIterable) {
!(i%2) && arr.push(i);
}
return arr;
}
console.log(getOdd()); //[ 0, 2, 4 ]

5). Symbol.asyncIterator 符号指定了一个对象的默认异步迭代器。如果一个对象设置了这个属性,它就是异步可迭代对象,可用于for await...of循环。

 let asyncIterable = {
[Symbol.asyncIterator]() {
return {
i: 0,
next() {
if (this.i < 3) {
return Promise.resolve({ value: this.i++, done: false });
} return Promise.resolve({ done: true });
}
};
}
}; (async function() {
for await (num of asyncIterable) {
console.log(num); // 0 1 2
}
})();

***** 其他属性和方法可以参考 MDN 文档

***** 参考文献

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

http://es6.ruanyifeng.com/#docs/symbol

 
 

ES6 之 Symbol的更多相关文章

  1. ES6之Symbol

    ES6中Symbol是为了防止属性名冲突而引入的,是独一无二的.Symbol值是通过Symbol函数生成.Symbol值不能与其他类型的值运算否则会报错且Symbol的值可以转换为字符串或者是布尔值但 ...

  2. ES6(六) --- Symbol

    概述: ES5 中属性名都是字符串,这容易就造成命名的冲突,特别是在混入模式(mixin模式)下.为解决这个问题ES6 引入了Symbol, Symbol是一种新的基本数据类型,表示独一无二的值!   ...

  3. Es6(Symbol,set,map,filter)

    首先再讲这几个新东西之前,先说一个Es6中新出的扩展运算符(...) 1.展开运算符,就是把东西展开,可以用在array和object上 比如: let a=[,] let b=[,...a,]//[ ...

  4. JS的ES6的Symbol

    一.Symbol 1.什么是Symbol: Symbol是ES6新添加的原始类型(ES5已有原始数据类型:String,Number,boolean,function,undefined,object ...

  5. ES6的Symbol

    let s = Symbol(); alert(typeof(s)); // Symbol函数可以接受一个字符串作为参数,表示对 Symbol 实例的描述,主要是为了在控制台显示,或者转为字符串时,比 ...

  6. es6(9)--Symbol

    //Symbol生成一个独一无二的值,生成的值不会相等 { //声明1 let a1=Symbol(); let a2=Symbol(); console.log(a1===a2);//false / ...

  7. ES6 中 Symbol.split的用法

    class Split1 { constructor(value) { this.value = value; } [Symbol.split](string) { var index = strin ...

  8. ES6初识-Symbol

    Symbol的概念 变量是独一无二的 let a1=Symbol(); let a2=Symbol(); a1和a2严格意义不相等 let a3=Symbol.for('a3'); let a4=Sy ...

  9. ES6中的Symbol类型

    前面的话 ES5中包含5种原始类型:字符串.数字.布尔值.null和undefined.ES6引入了第6种原始类型——Symbol ES5的对象属性名都是字符串,很容易造成属性名冲突.比如,使用了一个 ...

随机推荐

  1. mysql5.7兼容老版本不校验日期等字段

    升级mysql5.7时,字段校验出现2个问题,一是不识别日期字段的 0000-00-00 00:00:00,二是有些非空且无默认值的字段,插入时必须指定具体的值. 修改/etc/my.cnf 可在[m ...

  2. LuoguP5540:【模板】最小乘积生成树(几何逼近)

    题意:给定N点,M边,每条边有两个属性(a,b),现在让你选N-1条边出来,然后使得∑a*∑b最小.N<200,M<1e4: 思路:我们把∑a看成x,∑b看成y,那么一个方案对应一个二维坐 ...

  3. C语言实现Socket简单通信

    环境是linux,不过应该没什么影响,因为只用到了socket的基本用法,没有涉及pthread等. 分为服务器端和客户端,服务器端监听端口发来的请求,收到后向客户端发送一个Hello World,客 ...

  4. 【LG2605】[ZJOI2010]基站选址

    [LG2605][ZJOI2010]基站选址 题面 洛谷 题解 先考虑一下暴力怎么写,设\(f_{i,j}\)表示当前\(dp\)到\(i\),且强制选\(i\),目前共放置\(j\)个的方案数. 那 ...

  5. ZROI 暑期高端峰会 A班 Day4 生成函数

    一般生成函数 很普及组,不讲了 生成函数是一种形式幂级数,也就是我们只关心系数,不关心未知数具体的值. 比如 \(\sum\limits_{i\ge 0}x^i=\frac{1}{1-x}\).虽然只 ...

  6. Spring Security教程之整合SpringMVC(六)

    一.前言 Spring Security系列教程中,前五篇为同一人所写,而本文是博主依据第三方文章整合而出,与前五篇文章的作者不是同一系列. 但本文以前五篇文章为基础,在前面文章所建立的Spring ...

  7. Guava---缓存之LRU算法

    随笔 - 169  文章 - 0  评论 - 292 GuavaCache学习笔记一:自定义LRU算法的缓存实现   前言 今天在看GuavaCache缓存相关的源码,这里想到先自己手动实现一个LRU ...

  8. 2018-2019-2 20165315《网络对抗技术》Exp9 Web安全基础

    2018-2019-2 20165315<网络对抗技术>Exp9 Web安全基础 目录 一.实验内容 二.实验步骤 1.Webgoat前期准备 2.SQL注入攻击 Command Inje ...

  9. Apache Beam实战指南 | 大数据管道(pipeline)设计及实践

    Apache Beam实战指南 | 大数据管道(pipeline)设计及实践  mp.weixin.qq.com 策划 & 审校 | Natalie作者 | 张海涛编辑 | LindaAI 前 ...

  10. 依赖注入之unity(winform方式)

    依赖注入之unity(winform方式) 要讲unity就必须先了解DI和IOC及DIP,如下链接提供DI和IOC的基础:https://www.cnblogs.com/zlp520/p/12015 ...