symbol

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”无类型偏好
数字转换时优先级排序:
  1.     调用valueOf()如果为原始值 返回
  2.     调用toString()如果结果为原始值 返回
  3.     如果再无可选值 抛出异常

字符串转换优先级
  1.         调用toString()如果结果为原始值 返回
  2.         调用valueOf()方法,结果为原始值 返回
  3.         抛出异常    
大多数情况下 默认按数字型处理
默认模式只用于 ==、+和给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就不用了

















评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值