了解内置Symbol对象


symbol内置属性通常用来改变对象的默认行为。由于浏览器的支持问题,可以把代码拷贝到Vue或者React框架内查看效果。

symbol.iterator

    当使用for in时会调用该遍历器,举例:

class DefaultArray extends Array{
    constructor(...args){
       super(...args);
    }
    *[Symbol.iterator](){//对象的Symbol.iterator属性,指向该对象的默认遍历器方法
        let i = 0;console.log("call iterator");
        while (this[i] != undefined) {
            yield this[i];
            ++i;
        }
    }
}
let arr=new DefaultArray(1,2,3);
for(let i of arr){
    console.log(i);
}
//类似于generator函数
function *Iterator(arr){
    for(let i=0;i<arr.length;i++){
       yield arr[i];
    }
    return true;
}
let myarr=Iterator([5,4,3,2,1]);
console.log(myarr.next());
for(let j of myarr){
    console.log(j);
}
//打印
//{value: 5, done: false}
// 4
//3
//2
//1

symbol.asyncIterator

    当使用for await…of时会调用该遍历器,举例:

class DefaultArray extends Array{
    constructor(...args){
       let arr=super(...args);
       this.realValue=arr;
    }
    makeAsyncName(str){//构造一个类似异步请求的方法
        console.log("call asyncIterator:"+str);
        return new Promise((rs,rj)=>{
            setTimeout(()=>{rs(str)},5000);
        });
    }
    *[Symbol.asyncIterator](){//定义异步遍历器
        let i=0;
        while (this[i] != undefined) {
            yield this.makeAsyncName(this[i]);
            ++i;
        }
    }
}
let arr=new DefaultArray(1,2,3);
async function run() {
    for await (const value of arr) {
        console.log("async::"+value);
    }
}
run();
//首先显示call asyncIterator:1 
//五秒后显示下面两个,意味着只有取到了先前结果,才去获取下一个以此类推
//async::1
//call asyncIterator:2

symbol.toPrimitive

    当使用各种显示或隐式转换时会调用该方法,当有这个属性时将不会调用toString或valueOf方法转换。举例:

class DefaultArray extends Array{
    constructor(...args){
       let arr=super(...args);
       this.realValue=arr;
    }
    [Symbol.toPrimitive](hint){
    //对象的Symbol.toPrimitive属性,指向ToPrimitive。该对象被转为原始类型的值时,会调用这个方法,返回该对象对应的原始值类型值。
    //Symbol.toPrimitive被调用时,会接受一个字符串参数,表示当前运算的模式,一共有三种模式:
    // Number:该场合需要转换为数值。
    // String:该场合需要转成字符串。
    // Default:该场合可以转成数值,也可以转成字符串。
        console.log(hint);
        switch(hint){
            case "number" :
                return NaN;
            case "string" :
                return "[DefaultArray Array]";
            case "default" :
                return "default";
            default :
                throw new Error();
        }
    }
    toString(){
        console.log("get string");
        return "[DefaultArray Array]";
    }
    valueOf(){
        console.log("get value");
        return NaN;
    }
}
let arr=new DefaultArray(1,2,3);
console.log(Number(arr));//NaN 
console.log(String(arr));//[DefaultArray Array]
console.log(`${arr}::es6string`);//[DefaultArray Array]::es6string
console.log(Boolean(arr));//true 没有经过调用
console.log(+arr);//NaN
//当使用+转换类型时无法判断转化为数字还是字符
console.log(arr+"");//default 
console.log(arr+1);//default
console.log(!arr);//false 没有经过调用

symbol.species

    species 访问器属性允许子类覆盖对象的默认构造函数。当使用数组方法如map,concat等返回一个新的数组,我们可以通过这个属性设置这些派生的类。

class DefaultArray extends Array{
    constructor(...args){
       super(...args);
    }
    static get [Symbol.species](){
        //A function valued property that is the constructor function that is used to create derived objects.
        //对象的Symbol.species属性,指向一个构造函数。创建衍生对象时,会使用该属性。
       return this;//默认this也就是本身的构造函数 可设置为如Array等构造函数
    }
}
let arr=new DefaultArray(1,2,3);
let extendArr=arr.concat([4,5,6]);
console.log(extendArr);//指向的this,DefaultArray(6) [1, 2, 3, 4, 5, 6]
console.log([...extendArr]);//(6) [1, 2, 3, 4, 5, 6] 只有使用继承Array的方法才有效

symbol.unscopables

    对象属性,在使用with绑定环境的时候排除自身和继承的属性名。

class DefaultArray extends Array{
    constructor(...args){
       let arr=super(...args);
       this.realValue=arr;
    }
    get [Symbol.unscopables](){//使用width时从对象中排除
      return {
          realValue:true //排除此选项
      }
    }
}
let arr=new DefaultArray(1,2,3);
with(arr){
    console.log(realValue);//Uncaught ReferenceError: realValue is not defined
}

symbol.hasInstance

    这个方法决定了构造函数是否识别一个对象为它的实例。使用instanceof 操作符时调用。

class DefaultArray extends Array{
    constructor(...args){
       super(...args)
    }
	static [Symbol.hasInstance](RightParam){//对象的Symbol.hasInstance属性,指向内部方法,当其他对象使用instanceOf运算符,判断是否为该对象的实例时,会调用这个方法。
	console.log(RightParam);
	        return true
	        //RightParam instanceof DefaultArray;
	 }
}
let arr=new DefaultArray(1,2,3);
console.log(arr instanceof DefaultArray);

Symbol.isConcatSpreadable

一个值,指定了Array.prototype.concat是否能展开数组

class DefaultArray extends Array{
    constructor(...args){
       super(...args);
    }
    get [Symbol.isConcatSpreadable](){//对象的Symbol.isConcatSpreadable属性等于一个布尔值,表示该对象用于Array.prototype.concat()时,是否可以展开
       return false;
    }
}
let arr=new DefaultArray(1,2,3);
let extendArr=arr.concat([4,5,6]);
console.log(extendArr);//DefaultArray(4) [DefaultArray(3), 4, 5, 6]
console.log([...arr,4,5,6]);//(6) [1, 2, 3, 4, 5, 6]

调用原型方法时会被调用的一些属性

  1. Symbol.toStringTag 一个属性,Object.prototype.toString会被调用。
class DefaultString extends String{
    constructor(str){
      super(str);
    }
    get [Symbol.toStringTag](){
        console.log("call tagString");
        return "DefaultString"
    }
}
console.log(Object.prototype.toString.call(new DefaultString()));//[object DefaultString]

2.Symbol.split 通过String.prototype.split调用

class Split1{
    [Symbol.split](str){
        console.log("call split",str);
        return str.split("");
    }
}
console.log("888".split(new Split1()));//(3) ["8", "8", "8"]

3.Symbol.search 通过String.prototype.search调用

class Split1{
    [Symbol.search](str){
        console.log("call search",str);
        return 0;
    }
}
console.log("888".search(new Split1()));//0

4.Symbol.replace 通过String.prototype.replace调用

class Split1{
    [Symbol.replace](str,rep){
        console.log("call replace",str,rep);//call replace 888 sss
        return "sss";
    }
}
console.log("888".replace(new Split1(),"sss"));//sss

5.Symbol.replace 通过String.prototype.match调用

class Split1{
    [Symbol.match](str){
        console.log("call match",str);//call match 888
        return "000";
    }
}
console.log("888".match(new Split1()));//000

6.Symbol.matchAll通过String.prototype.matchAll调用

class Split1{
    [Symbol.matchAll](regexp){
        console.log("call matchAll",regexp);//call matchAll 888
        return regexp.match(/[0-9]/g);
    }
}
console.log("888".matchAll(new Split1()));//(3) ["8", "8", "8"]
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值