ES6学习笔记(9)----Symbol
参考书《ECMAScript 6入门》
http://es6.ruanyifeng.com/
Symbol
1.symbol:Symbol是javascript的第七种原始数据类型,代表独一无二的值。前六种是Null,undefined,Boolean,String,Number,Object
生成symbol值的方式
let s1 = Symbol()
let s2 = Symbol('s2-symbol')//接受字符串作为参数来对symbol值进行描述
typeof s1 // Symbol
typeof s2 //Symbol
Symbol值是独一无二的
let s3 = Symbol()
let s4 = Symbol("s2-symbol")
s1 == s3 //false
s1 === s3 //false
Object.is(s1,s3) //false
s2 == s4 //false
s2 === s4 //false
Object.is(s2,s4) //false
let obj = {name:"testSymbol"}
Symbol(obj) //Symbol([object Object])
let c = Symbol(obj)
c //Symbol([object Object])
c === Symbol(obj) //false
s2//Symbol(s2-symbol)
String(s2)//'Symbol(s2-symbol)'
s2.toString()//'Symbol(s2-symbol)'
'abc'+s2 //报错 Uncaught TypeError: Cannot convert a Symbol value to a string
'abc'+s2.toString //"abcfunction toString() { [native code] }"
2.作为属性名的symbol
let symbolA = Symbol('A');
let symbolB = Symbol('B');
a.在对象外部,可以使用方括号和defineProperty方法两种方式将对象的属性名指定为symbol类型
let obj2 = {}
obj2[symbolA] = "test";
Object.defineProperty(obj2,symbolB,{value:"abc"});
obj2//{Symbol(A): "test", Symbol(B): "abc"}
b.读取对象中属性名为symbol的属性时,要用方括号,不能用点运算.
obj2.symbolA //undefined
obj2.symbolB //undefined
obj2[symbolA] //"test"
obj2[symbolB] //"abc"
c.在对象内部使用symbol定义对象的属性时,symbol必须放在对象当中
let obj3 = {
[symbolA] : "obj3-Symbol",
[symbolB](){
return "test symbolB"
}
}
obj3//{Symbol(A): "obj3-Symbol", Symbol(B): ƒ}
d.symbol可以用来定义常量,由于其独一无二的特性,可以使代码精确度更高
const staticVariable = Symbol();
3.属性名的遍历
Symbol定义的属性不是私有属性,但是并不能被常规方法遍历到,目前只能通过Reflect.ownKeys(obj)和Object.getOwnPropertySymbols(obj)两种方式遍历对象中的symbol属性
Reflect.ownKeys(obj4)//[Symbol(A), Symbol(B)]
Object.getOwnPropertySymbols(obj4)//[Symbol(A), Symbol(B)]
4.Symbol.for(),Symbol.keyFor()
Symbol()与Symbol.for()
相同点:都会生成新的Symbol
不同点
Symbol()每次都会生成新的Symbol,即使修饰参数一致。
Symbol.for(key)每次调用时,先会检查给定的key是否存在,如果存在,则返回这个已有的key对应的symbol值,如果不存在,则生成新的symbol值
let test1 = Symbol('test1');
let test2 = Symbol.for('test1');
let test3 = Symbol.for('test3');
let test4 = Symbol.for('test3');
test1 === test2 //false Symbol('test1')不会登记在全局环境中供搜索,所以Symbol.for('test1')在全局环境中搜索不到test1对应的symbol值,因此重新生成了一个symbol值。
test3//Symbol(test3)
test3 === test4 //true
Symbol.keyFor():返回一个已经登记的symbol值的key
Symbol.keyFor(test2)//'test1'
5.内置的Symbol值
Symbol.hasInstance
Symbol.isConcatSpreadable:用于判断一个数组或类数组调用concat时是否需要展开
数组:Symbol.isConcatSpreadable 默认值是undefined,代表展开;值为true时也代表展开,值为false时也代表不展开
let arr1 = [1,2,3];
let arr2 = [4,5,6];
let arr3 = ['a','b','c'];
arr1[Symbol.isConcatSpreadable]//undefined 展开
arr2[Symbol.isConcatSpreadable] = true;展开
arr3[Symbol.isConcatSpreadable] = false;不展开
arr3.concat(arr1,arr2)//[['a','b','c'], 1, 2, 3, 4, 5, 6]
类数组:Symbol.isConcatSpreadable值为true时代表不展开,值为false或者undefined时代表展开
let obj1 = {length:2,0:'a',1:'b'};
let obj2 = {length:3,0:'aa',1:'bb',2:'cc'};
let obj3 = {length:2,'0':'aaa',1:'bbb'};
obj1[Symbol.isConcatSpreadable];//undefined 不展开
obj2[Symbol.isConcatSpreadable] = true;展开
obj3[Symbol.isConcatSpreadable] = false;不展开
[].concat(obj3,obj1,obj2);//[{0: "aaa", 1: "bbb", length: 2, Symbol(Symbol.isConcatSpreadable): false}, "aa", "bb", "cc", {0: "a", 1: "b", length: 2}]
Symbol.species:对象的Symbol.species属性,指向一个构造函数。创建衍生对象时,会使用该属性。
定义Symbol.species属性要采用get取值器,默认的Symbol.species等同于下面的写法。
static get[Symbol.species](){return this;}
Symbol.match:对象的Symbol.match属性,对应一个方法。当对象的String.prototype.match方法调用时,会返回该方法的返回值。
Symbol.replace:对象的Symbol.replace属性,对应一个方法。当对象的String.prototype.replace方法调用时,会返回该方法的返回值。
Symbol.search:对象的Symbol.search属性,对应一个方法。当对象的String.prototype.search方法调用时,会返回该方法的返回值。
Symbol.split:对象的Symbol.split属性,指向一个方法。当该对象被String.prototype.split方法调用时,会返回该方法的返回值。
Symbol.iterator:对象的Symbol.iterator属性,指向对象的默认遍历器方法
Symbol.toPrimitive:对象的Symbol.toPrimitive属性指向一个方法。该对象被转为原始类型的值时,会调用这个方法,返回该对象对应的原始类型值。
let obj = {};
2*obj //NaN
2+obj //"2[object boolean]"
'[object boolean]' == obj //true
等同于
let obj = {
[Symbol.toPrimitive](hint) {
switch (hint) {
case 'number':
return NaN;
case 'string':
return 'str';
case 'default':
return '[object boolean]';
default:
throw new Error();
}
}
};
Symbol.toStringTag:对象的Symbol.toStringTag属性指向一个方法,在该对象上调用Object.prototype.toString方法时,如果它的属性存在,它的返回值会出现在toString方法返回的字符串之中,表示对象的类型。这个属性可以用来定制表示对象类型的如[object string]中 object后面的字符串
let obj = {"name" : "test"};
obj[Symbol.toStringTag] = 'boolean';
Object.prototype.toString.call(obj) //"[object boolean]"
Symbol.unscopables:对象的Symbol.unscopables属性指定一个对象,该对象规定当使用with关键字时,哪些属性会被with环境排除
ES6学习笔记(9)----Symbol的更多相关文章
- ES6学习笔记之Symbol
新的数据类型Symbol 1. 概述 ES5 的对象属性名都是字符串,这容易造成属性名的冲突.比如,你使用了一个他人提供的对象,但又想为这个对象添加新的方法(mixin 模式),新方法的名字就有可能与 ...
- es6学习笔记-class之一概念
前段时间复习了面向对象这一部分,其中提到在es6之前,Javasript是没有类的概念的,只从es6之后出现了类的概念和继承.于是乎,花时间学习一下class. 简介 JavaScript 语言中,生 ...
- JS&ES6学习笔记(持续更新)
ES6学习笔记(2019.7.29) 目录 ES6学习笔记(2019.7.29) let和const let let 基本用法 let 不存在变量提升 暂时性死区 不允许重复声明 块级作用域 级作用域 ...
- ES6学习笔记<五> Module的操作——import、export、as
import export 这两个家伙对应的就是es6自己的 module功能. 我们之前写的Javascript一直都没有模块化的体系,无法将一个庞大的js工程拆分成一个个功能相对独立但相互依赖的小 ...
- ES6学习笔记<四> default、rest、Multi-line Strings
default 参数默认值 在实际开发 有时需要给一些参数默认值. 在ES6之前一般都这么处理参数默认值 function add(val_1,val_2){ val_1 = val_1 || 10; ...
- ES6学习笔记<三> 生成器函数与yield
为什么要把这个内容拿出来单独做一篇学习笔记? 生成器函数比较重要,相对不是很容易理解,单独做一篇笔记详细聊一聊生成器函数. 标题为什么是生成器函数与yield? 生成器函数类似其他服务器端语音中的接口 ...
- ES6学习笔记<二>arrow functions 箭头函数、template string、destructuring
接着上一篇的说. arrow functions 箭头函数 => 更便捷的函数声明 document.getElementById("click_1").onclick = ...
- ES6学习笔记<一> let const class extends super
学习参考地址1 学习参考地址2 ECMAScript 6(以下简称ES6)是JavaScript语言的下一代标准.因为当前版本的ES6是在2015年发布的,所以又称ECMAScript 2015:也 ...
- ES6学习笔记之块级作用域
ES6学习笔记:块级作用域 作用域分类 全局作用域 局部作用域 块级作用域 全局作用域示例 var i=2; for (var i = 0; i < 10; i++) { } console.l ...
随机推荐
- Dedecms(织梦)文章内容页和图片集内容页,调用缩略图的方法
Dedecms(织梦)文章内容页和图片集内容页,调用缩略图的方法,亲测可用! Dedecms(织梦)首页的图片调用,相信大家已经非常的清楚,但是今天我在进行内容页的编写的时候,发现了内容页图片的调用问 ...
- java.lang.IllegalArgumentException: No converter found for return value of type: class com.st.bean.User
原因:springmvc默认是没有对象转换成json的转换器的,要添加jackson依赖 在pom.xml中添加 <dependency> <groupId>com.faste ...
- poj 1789 Truck History 解题报告
题目链接:http://poj.org/problem?id=1789 题目意思:给出 N 行,每行7个字符你,统计所有的 行 与 行 之间的差值(就是相同位置下字母不相同),一个位置不相同就为1,依 ...
- 转:Oracle客户端NLS_LANG参数的设置详解
原文:http://database.51cto.com/art/201107/279361.htm 我们知道,Oracle客户端语言支持可以通过NLS_LANG参数的设置来完成,不同的系统平台上NL ...
- 并不对劲的bzoj1758:p4292:[WC2010]重建计划
题目大意 \(n\)(\(n\leq10^5\))个点的一棵树,有边权\(w\),给定\(l,r\),求边数在\([l,r]\)中的路径的平均边权的最大值 题解 二分答案,判断时将边权变成\(w-mi ...
- Android Handler消息机制源码解析
好记性不如烂笔头,今天来分析一下Handler的源码实现 Handler机制是Android系统的基础,是多线程之间切换的基础.下面我们分析一下Handler的源码实现. Handler消息机制有4个 ...
- “玲珑杯”线上赛 Round #17 河南专场 A: Sin your life(和化积公式)
传送门 题意 略 分析 首先将sin(x)+sin(y)+sin(z)h转化成\(2*sin(\frac{x+y}2)*cos(\frac{x-y}2)+sin(z)\),而cos(z)=cos(-z ...
- HDU 5101
hdoj5101 lower_bound函数: 题意: 从两个不同集合拿出两个数,加的和大于k的可行的方案数 思路: 答案=从所有数中选择的两个加和大于k的数的方案数-在同一个集合中选择的两个加和大于 ...
- bzoj 2251: [2010Beijing Wc]外星联络【SA】
先求SA,然后按字典序从小到大枚举子串,每到一个后缀从长到短枚举子串(跳过长为he[i]的和前一段重复的子串),然后维护一个点p,保证i~p之间最小的he>=当前枚举长度,p是单调向右移的 然后 ...
- bzoj 3365: [Usaco2004 Feb]Distance Statistics 路程统计【容斥原理+点分治】
统计在一个root下的两个子树,每个子树都和前面的运算一下再加进去对于这种需要排序的运算很麻烦,所以考虑先不去同子树内点对的算出合法点对个数,然后减去每一棵子树内的合法点对(它们实际上是不合法的,相当 ...