symbol是用来处理私有成员的原始属性 与 字符串、boolean一个等级
用于处理一些在作用域中 不冲突 且对值没有关心的属性
创建symbol
let firstName = Symbol();
let person = {};
person[firstName]='cccc';
console.info(firstName);//Symbol()
console.info(person[firstName]);//cccc
Symbol可以添加一个文本描述 可访问 (建议每次都加一个,用于加强阅读和调试)
Symbol的描述存储在Description中 只有调用symbol的toString()方法才可以读取
在程序中可以用 typeof [Symbol定义变量] ==='symbol'来判断 是否是symbol类型
symbol的使用方法:
所有可计算属性名的地方:
可计算字面量属性名
Object.defineProperty()方法
Object.defineProperties()方法
let firstName = Symbol('first name');
//作为可计算字面量
let person = {
[firstName]: "xiao"
}
//使用defineProperty()方法改变对象
Object.defineProperty(person, firstName, {
writable: false
}); //修改为只读
let lastName = Symbol('last name');
Object.defineProperties(person, {
[lastName]: {
value: 'min',
writable: false
}
});
console.info(person); //{ [Symbol(first name)]: 'xiao' }
console.info(person[lastName]); //min
Symbol共享体系:
symbol通过一个全局的注册表来共享一个symbol
用Symbol.for()进行访问:
如果没有 则创建一个新的,如果有 则 返回拥有的
let uid = Symbol.for('uid');
let obj = {
[uid]: '123456'
};
console.info(obj[uid]); //123456
console.info(uid); //Symbol(uid)
let uid2 = Symbol.for('uid');
console.info(uid2 === uid); //true
console.info(obj[uid2]); //123456
Symbol.forKey()用键值 进行检索 返回为 键的描述
let uid = Symbol.for('uid');
console.info(Symbol.keyFor(uid));//uid
let uid2 = Symbol.for('uid');
console.info(Symbol.keyFor(uid2));//uid uid1和uid2调用的是同一个Symbol
let uid3=Symbol('uid');
console.info(Symbol.keyFor(uid3));//undefined 因为uid3只是注册到局部 并没有注册到全局
Symbol与类型的强转:
String值:
可以转换
转换时不能拼接
let uid = Symbol('uid');
let changeValue=String(uid);
console.info(changeValue);//Symbol(uid)
let changeValue=String(uid+'');//error:Identifier 'changeValue' has already been declared
Number值:
强转报错
Boolean值:
只能为true
Symbol属性检测:
Object.keys()和Object.getOwnPropertyNames()可以检索对象的所有属性名
Object.keys():返回所有可枚举的属性名
Object.getOwnPropertyNames():不考虑枚举性,一律返回
如上两个方法都不支持symbol
可以用 Object.getOwnPropertySymbols();
let uid = Symbol.for('uid');
let uid2 = Symbol.for('uid2');
let obj={
[uid]:'12345',
[uid2]:'54321'
};
let symbols=Object.getOwnPropertySymbols(obj);
console.info(symbols);//[ Symbol(uid), Symbol(uid2) ]
通过well-known Symbol暴露内部操作:
Sysbol.hasInstance() :
功能:用于确定对象是否是函数的实例
该方法在所有Function.phototype中定义
该方法不可写,不可配置,不可枚举
obj instanceof Array ;等同于 Array[Symbol.hasInstance](obj)
可用于定义一个无实例的函数:
function MyObj(){
}
Object.defineProperty(MyObj,Symbol.hasInstance,{
value:function(v){
return false;
}
})
let obj=new MyObj();
console.info(obj instanceof MyObj);//false
在value设置中 返回true则检测成功
作者不推荐
Symbol.isCOncatSpreadble:
concat()用于数组的拼接 复制
在concat()函数中,数组会自动拆分成单独的元素 ,Symbol.isConcatSpreadable属性为一个boolean值,当为true时 对象拥有length和数字键
let obj={
0:'hello',
1:'world',
length:2,
[Symbol.isConcatSpreadable]:true
}
let message=['hi'].concat(obj);
console.info(message);//[ 'hi', 'hello', 'world' ]
console.info(message.length);//3
可用于对象模拟数组:
也可以把Symbol.isCOncatSpreadble设置为false预防分解
Symbol.match() Symbo.replace()和Symbolsearch()和Symbol.split()
match(regex):确定给定字符串是否匹配正则
replace(regex,replacement)将字符串中与正则表达式匹配的部分替换为 replacement
search(regex)返回字符串匹配正则的索引
split(regex)按照匹配正则表达式regex的元素将字符串分切为数组
在ES6中,将以上四个方法的regExp特性全部外包出来
Symbol.match(str) 接受一个字符串,匹配成功 返回匹配元素数组,否则返回null
Symbol.replace(str,reStrMent)接受一个字符串,匹配成功替换为替换的字符串 返回
Symbol.search(str)接受一个字符串参数 如果找到 返回索引下标 否则返回-1
Symbol.split(str) 接受一个字符串,将匹配到的分解 返回一个包含分解的字符串
如果在对象中定义这些属性,不用正则表达式也能在对象中得到模式匹配结果
//等价与/^.{10}$/
let hasLength10 = {
[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 = "helloWorld"; //10
let message2 = "hello World"; //11
//match匹配
console.info(message1.match(hasLength10)); //[ 'helloWorld' ]
console.info(message2.match(hasLength10)); //null
//replace匹配
console.info(message1.replace(hasLength10, 'ccc')); //ccc
console.info(message2.replace(hasLength10, 'ccc')); //hello World
//search匹配
console.info(message1.search(hasLength10)); //0
console.info(message2.search(hasLength10)); //-1
//split匹配
console.info(message1.split(hasLength10)); //[ 'helloWorld' ]
console.info(message2.split(hasLength10)); //[ <1 empty item> ]
//适用于更加复杂的模式匹配 一般的还是用传统正则吧,写这么多怪累的
Symbol.toPrimitive方法
js进行类型转换时调用 有三种结果 “string”字符串、“number”数字、“default”无类型偏好
数字转换时优先级排序:
- 调用valueOf()如果为原始值 返回
- 调用toString()如果结果为原始值 返回
- 如果再无可选值 抛出异常
字符串转换优先级
- 调用toString()如果结果为原始值 返回
- 调用valueOf()方法,结果为原始值 返回
- 抛出异常
大多数情况下 默认按数字型处理
默认模式只用于 ==、+和给Date对象传递参数
function Teperature(degrees){
this.degrees=degrees;
}
Teperature.prototype[Symbol.toPrimitive] = function (hint){
switch(hint){
case "string":
return this.degrees+'\u00b0';//+°
case "number":
return this.degrees; //数字结果
case "default":
return this.degrees+'degrees';//默认+degrees
}
}
var freezing = new Teperature(32);
console.info(freezing+'!'); //32degrees!
console.info(freezing/2); //16
console.info(String(freezing));//32°
Symbol.toStringTag属性:
每个iframe都是js执行的另一个完全不同的环境
针对类型识别的解决方案:
调用对象标准中的toString()方法每次都会返回预期的字符串,可用这个来判断类型
//判断是否是数组
function isArray(value){
return Object.prototype.toString.call(value)=== "[object Array]":
}
console.info(isArray([]);//true
在es5中判断json是本身提供的还是其它库提供的:
//判断是否是原生JSON
function supportNativeJson(){
return typeof JSON !=="undefined" &&
Object.prototype.toString.call(JSON) === '[object JSON]';
}
在es6中定义对象字符串标签:
对象可以通过Symbol.toStringTag来改变toString的值
function Person(name) {
this.name = name;
}
Person.prototype[Symbol.toStringTag] = "Person";
var test = new Person('kazi');
console.info(test.toString()); //[object Person]
console.info(Object.prototype.toString.call(test)); //[object Person]
也可以重写toString()让普通调用时返回正常toString值:
function Person(name) {
this.name = name;
}
Person.prototype[Symbol.toStringTag] = "Person";
Person.prototype.toString = function() {
return this.name;
}
var test = new Person('kazi');
console.info(test.toString()); //kazi
console.info(Object.prototype.toString.call(test)); //[object Person]
也可以把toStringTag改为原生的几个
也可以把原生的对象改为其它
以上两种就是提一下,别这么干....
Symbol.unscopables属性:
考虑到不使用with就不用了