全部
常见问题
产品动态
精选推荐

Symbol类型详解

管理 管理 编辑 删除
  1. symbol类型通过Symbol函数生成,用于表示独一无二的值(不使用new关键字,直接调用即可创建。例:const s = Symbol("str"))
  2. 即使使用相同的字符串来创建Symbol类型的值,这些值也是不同的

3. symbol值可以调用 toString方法,也可以通过Boolean()转为 布尔值

a.symbol本身转为布尔值时为true,取反为false

b.toString调用后会返回Symbol(str)

4. 在ES6中,支持用表达式 (变量)作为属性名,但表达式必须放在方括号里,由于每个Symbol值都是独一无二的,就可以用Symbol值作为属性名,且不会和其他属性名重复

5. 使用symbol值作为属性名的属性访问只能使用name和 这个symbol值,例:obj[name]

6. 属性名遍历

a. symbol类型的属性并不是私有属性,但不能通过for in遍历到,也不能被Object.keys() ,Object。getOwnProperNames(),Json.stringify()获取到

b. symbol类型属性名可以通过Object.getOwnPropertySymbol()获取,但只能获取到symbol类型的属性名

c. 使用ES6新提供的Reflect对象的 静态方法Reflect.ownKeys()可以获取全部属性名 ,包括symbol类型和非symbol类型

7. symbol的静态方法

a. Symbol.for()

使用Symbol.fro()方法传入字符串,会先检查有没有使用这个字符串调用Symbol.for创建的symbol值,如果有,就返回该值,没有则进行创建

通过Symbol.for创建的symbol值是全局范围内的

b. Symbol.keyFor()

调用Symbol.keyfor传入一个symbol值可以返回该值在全局注册的键名,例

const sym = Symbol.for("aaa");
console.log(Symbol.keyFor(sym));
//会返回aaa

8. ES6的11个内置Symbol值

a. Symbol.hasInstance

对象的Symbol.hasInstance指向一个内部方法,如果给一个对象设置了以Symbol.hasInstance为属性名的方法,当其他对象使用instanceof来判断是否为该对象实例时,会调用这个方法,传入的参数为被判断的这个对象

const obj = {
    [Symbol.hasInstance](obj2){
        console.log('obj2');
        //调用后会打印出{a:111}这个对象
    }
};

console.log({a:111} istanceof obj);
//{a:111}会作为obj2传入Symbol.hasInstance

b. Symbol.isConcatSpreadable

该属性是一个可读写的布尔值,默认值为undefined,该属性控制数组是否能被扁平化,当值为false时,数组不能被扁平化,为true或undefined则可以,例:

let arr1 = [1,2];
console.log([].concat(arr1,[3,4]));
//打印结果为[1,2,3,4]
console.log(arr1[Symbol.isConcatSpreadable]);
//此时该属性值为默认的undefined

arr1[Symbol.isConcatSpreadable] = true;
//把属性值设置为true
console.log([].concat(arr1,[3,4]));//结果同上
console.log(arr1[Symbol.isConcatSpreadable]);
//属性值为true

arr1[Symbol.isConcatSpreadable] = false;
//再设置为false
console.log([].concat(arr1,[3,4]));
//此时的结果变成了[Array(2), 3, 4]
//展开后是[[1, 2, Symbol(Symbol.isConcatSpreadable): false],3,4]
//这里的Symbol(Symbol.isConcatSpreadable): false]不是一个元素,而是一个属性
console.log(arr1[Symbol.isConcatSpreadable]);
//false

c. Symbol.species

定义一个类C,使其继承自Array,再给类C创建一个实例对象c,c就能继承Array原型对象上的方法,通过c的map方法衍生一个a对象,分别打印a instanceof C和a instanceof Array,发现结果都为true,说明a既是C的实例对象,也是Array的实例对象

class C extends Array{
    getName(){
        return 'aaa';
    }
};
const c = new C(1,2,3);
const a = c.map(item=>item+1)
console.log(a instanceof Array)
console.log(a instanceof C)//两个结果都为true
console.log(a.getName())//aaa

如果需要让a只是Array的实例而不是C的实例,就需要使用Symbol.species,给C定义一个名为Symbol.specied的静态get存取器方法,并在该方法中返回要构造衍生数组的构造函数

class C extends Array{
    static get[Symbol.species](){
        retrun Array;
    }
    getName(){
        return 'aaa';
    }
};
const c = new C(1,2,3);
const a = c.map(item=>item+1)
console.log(a instanceof Array)//打印true
console.log(a instanceof C)//结果为false
console.log(a.getName())//a不是C的实例,也不能调用getName方法,会报错a.getName is not a function

d. Symbol.match,Symbol.replace,Symbol.search,Symbol.split

这四个都指向一个内部方法,当在字符串上调用match,replace,search,和split方法时,会调用这个方法

let obj = {
  [Symbol.match](str){
    return str.length
  }
};

console.log('aaaaa'.match(obj));//返回值为5

e. Symbol.iterator

数组的Symbol.iterator方法指向该数组的默认遍历器方法,该属性是可写的,可以自定义遍历器方法

f. Symbol.toPrimitive

Symbol.toPrimitive指向一个内部方法,当对象被转为原始类型是会调用这个方法,这个方法的参数是该对象被转为的类型

const obj = {
  [Symbol.toPrimitive](type){
    console.log(type);
  }
};

const a = obj++
//调用方法后会打印number

g. Symbol.toStringTag

对象的Symbol.toStringTag属性可以是一个字符串也可以是一个存取器get方法,当对象调用toString方法时,会返回[object 返回值]

let obj = {
    //属性值为存取器get方法
  get [Symbol.toStringTag](){
    return 'aaa';
  }
};

let obj2 = {
    //字符串属性值
  [Symbol.toStringTag]:'bbb'
}

console.log(obj.toString());
//打印[object aaa]
console.log(obj2.toString());
//打印[object bbb]

h. Symbol.unscopables

对象的该属性指向一个对象,可以控制这个对象的属性是否被with环境过滤

const obj={
  a:111,
  b:222,
  c:333,
}

obj[Symbol.unscopables]={
  a:true,
  b:false
}

with(obj){
  // console.log(a);
    //因为对a设置为了true,所以a属性会被with环境过滤掉,不能通过with访问,会报错
  console.log(b);//222
  console.log(c);//333
}

console.log(obj[Symbol.unscopables]);
//{a: true, b: false}


风轻云淡 最后编辑于2023-03-18 12:22:02

快捷回复
回复({{post_count}}) {{!is_user ? '我的回复' :'全部回复'}}
回复从新到旧

{{item.user_info.nickname ? item.user_info.nickname : item.user_name}} 作者 管理员 企业

{{item.floor}}# 同步到gitee 已同步到gitee {{item.is_suggest==1? '取消推荐': '推荐'}}
{{item.floor}}#
{{item.user_info.title}}
附件

{{itemf.name}}

{{item.created_at}}  {{item.ip_address}}
{{item.like_count}}
{{item.showReply ? '取消回复' : '回复'}}
删除
回复
回复

{{itemc.user_info.nickname}}

{{itemc.user_name}}

作者 管理员 企业

回复 {{itemc.comment_user_info.nickname}}

附件

{{itemf.name}}

{{itemc.created_at}}   {{itemc.ip_address}}
{{itemc.like_count}}
{{itemc.showReply ? '取消回复' : '回复'}}
删除
回复
回复
查看更多
回复
回复
774
{{like_count}}
{{collect_count}}
添加回复 ({{post_count}})

相关推荐

风轻云淡 作者
社区运营专员---高冷のBoy | 呆萌のGirl

回答

1081

发布

1723

经验

38859

快速安全登录

使用微信扫码登录
{{item.label}} {{item.label}} {{item.label}} 板块推荐 常见问题 产品动态 精选推荐 首页头条 首页动态 首页推荐
加精
取 消 确 定
回复
回复
问题:
问题自动获取的帖子内容,不准确时需要手动修改. [获取答案]
答案:
提交
bug 需求 取 消 确 定

快速安全登录

使用微信扫码登录
CRMEB客服

CRMEB咨询热线 咨询热线

400-8888-794

微信扫码咨询

CRMEB开源商城下载 开源下载 CRMEB官方论坛 帮助文档
返回顶部 返回顶部
CRMEB客服