ES6笔记( 七 )- Symbol


ES6笔记( 七 )- Symbol

符号: 符号是ES6新增的一个数据类型, 通过Symbol(符号名)来创建

目录:

    符号概览
    普通符号
    共享符号
    知名( 具名, 公共 )符号

符号概览

在开始之前, 咱先回顾一下ES6之前的我们所知道的数据类型

string, number, boolean, object, undefined, null

符号设计的初衷: 是为了给对象设置私有属性

在过去我们JS是没有私有成员这一说的( 当然你通过特殊手段实现的不算 ), 但是私有成员又是非常有必要的, 特别是想__proto__这类属性, 官方其实是不想让你看到的, 但是我们不仅看到了我们还操控了, 相较于我们个人而言, 自己在开发的时候也有很多东西是想直接不让别人操控的, 过去我们都会习惯性的用语义化命名( 变量前加上_)来提示其他合作伙伴这个属性是我私有的, 你别去操作

ES6的Symbol( 符号 )帮助我们处理了这个问题, 至于怎么处理的, 继续往下看吧

普通符号
符号的创建

const syb = Symbol();
// Symbol函数接收的参数为描述信息, 用于方便开发者调试( 知道这个符号到底是干什么用 )
const syb2 = Symbol('helloWorld');

符号具有以下特点:

    没有字面量, 要想使用符号必须通过Symbol函数调用
    typeof符号为Symbol
const syb = Symbol();
console.log( typeof syb ); // symbol

    每次调用Symbol得到的符号永远不相等, 无论符号名是否相同
const syb = Symbol('abc');
const syb2 = Symbol('cbd');
console.log(syb === syb2); // false

    符号可以作为对象的属性名存在, 这种属性称之为符号属性

    由于第三点和这一点, 开发者可以通过精妙的设计, 让符号属性无法通过常规操作被外界访问到

    const obj = (function () {

    const valueSymbol = Symbol('valueSymbol');

    return {
    [valueSymbol]: '我是永远无法被更改的',
    name: 'loki'
    }
    }())

    console.log(obj)
    obj.name = 'thor';
    console.log(obj.name); // thor
    console.log(obj[Symbol('valueSymbol')]); // undefined

    如上, 我们的Symbol(valueSymbol)属性别人虽然可以看到但是永远无法访问和修改, 比我们自己写_注明安全多了吧

    符号属性是不可枚举的, 因此在for…in中无法读取到符号属性, Object.keys也无法读取到符号属性

    const obj = {
    name: 'loki',
    [Symbol('helloWorld')]: 'helloWorld'
    }

    for(const item in obj) {
    console.log(item); // 只会输出name
    }

    const keys = Object.keys( obj );

    console.log(keys); // ["name"]

    Object.getOwnPropertyNames尽管可以得到无法枚举的属性, 但是仍然无法读取到Symbol属性

    const obj = {
    name: 'loki',
    [Symbol('helloWorld')]: 'helloWorld'
    }

    const keys = Object.getOwnPropertyNames( obj );
    console.log(keys); // ["name"]

    ES6新增Object.getOwnPropertySymbols方法, 用于获取符号列表, 同时可以进行操作

    const obj = {
    name: 'loki',
    [Symbol('helloWorld')]: 'helloWorld'
    }

    const symbols = Object.getOwnPropertySymbols( obj );

    console.log(symbols); // [Symbol(helloWorld)]

    console.log(obj[ symbols[0] ]); // helloWorld

    obj[ symbols[0] ] = 123;

    console.log(obj[ symbols[0] ]); // 123

    符号无法进行隐式类型转换, 因此无法用于数学运算, 字符串拼接或者其他隐式类型转换的场景, 但是符号可通过String构造函数进行显示类型转换, console.log函数能够输出符号也是因为在log函数中进行了显示转换

const symb = Symbol('hello');
const str = '123' + symb; // 这一句直接报错 Cannot convert a Symbol value to a string

共享符号

啥是共享符号, 共享符号就是说, 在某些情况下, 你想让两个对象或者两个地方用同一个符号, 我们用上面普通符号的知识往往会这样做

const symb = Symbol('needRepeatSymbol');

const obj1 = {
[symb]: 'helloWorld'
}

const obj2 = {
[symb]: 'helloWorld2'
}

const symbs1 = Object.getOwnPropertySymbols(obj1);
const symbs2 = Object.getOwnPropertySymbols(obj2);

console.log(symbs1[0] === symbs2[0]); // true

上面那么写其实略显麻烦, 而且有一些问题( 比如如果这两哥们在不同的组件和作用域下, 那你还怎么给人家共享一个Symbol )

所以ES6还推出了一个创建共享符号的api: Symbol.for

Symbol.for规定只要你的符号长得一样, 那无论你创建多少次都是同一个, 在不同的作用域都适用

const symb = Symbol.for('hello');
const symb2 = Symbol.for('hello');

const symb3 = Symbol('hello');
const symb4 = Symbol('hello');

console.log(symb === symb2); // true
console.log(symb3 === symb4); // false
console.log(symb === symb3); // false

知名( 具名, 公共 )符号

知名符号是一些具有特殊含义的符号, 通过Symbol的静态属性可以拿到, 就是系统已经给你内置好了, 不是你自己写的, 包括系统很多的内置方法都有或多或少的用到这些知名符号

    Symbol.hasInstance

该符用于定义构造函数的静态成员, 它将影响instanceof的判定

const arr = [1 ,2, 3];

console.log(arr instanceof Array); // true, 这是我们的常规写法

// 同时arr instanceof Array也等效于如下写法
console.log(Array[Symbol.hasInstance](obj)); // true

上面说到它将影响instanceof的判定, 因为他是insetanceof的底层实现, 那我们可以来试一试

Object.defineProperty(Array, Symbol.hasInstance, {
value: function( obj ) {
return false;
}
})

const arr = [1, 2, 3];
console.log( arr instanceof Array ); // false

经过我们这么一折腾, 数组的instanceof已经出现了事与愿违的效果了, 所以这些知名符号其实就是ES6暴露给我们开发者, 让我们在某些情况下是可以直接参与到JS的内部实现的, 否则比如instanceof你看到他这语法都能给你整懵圈, 这是咋实现的啊? a instanceof b, 现在你就知道了吧

    【 扩展 】Symbol.isConcatSpreadable

该符号会影响数组的concat

const arr = [1, 2, 3];

const arr3 = arr.concat( 10, [4, 5, 5] );

console.log(arr3); // [1, 2, 3, 10, 4, 5, 5]

// 上面我们会发现concat方法在连接数组的时候会将数组展开, 如果我们不想让他展开
// 就操作Symbol.isConcatSpreadable

const newArr = [4, 5, 5];
newArr[Symbol.isConcatSpreadable] = false; // 设置为true就会展开, false就不会
const newArr2 = arr.concat(10, newArr);

console.log(newArr2); // [1, 2, 3, 10, [4, 5, 5]]

    【 扩展 】Symbol.toPrimitive

该符号会影响类型转换的结果

const obj = {
a: 1,
b: 123
}

const resp = obj + 123;
console.log(resp); // [object Object]123

// 上面的结果是因为发生了隐式类型转换, 过去我们是无法参与到这种JS的内部操作的, 但现在可以

obj[Symbol.toPrimitive] = function() {
return 10;
}

const newResp = obj + 123;
console.log(newResp); // 133还是number类型的

    其他知名符号就不一一书写了, 可以直接去MDN的Symbol中可以查看

原创:https://www.panoramacn.com
源码网提供WordPress源码,帝国CMS源码discuz源码,微信小程序,小说源码,杰奇源码,thinkphp源码,ecshop模板源码,微擎模板源码,dede源码,织梦源码等。

专业搭建小说网站,小说程序,杰奇系列,微信小说系列,app系列小说

ES6笔记( 七 )- Symbol

免责声明,若由于商用引起版权纠纷,一切责任均由使用者承担。

您必须遵守我们的协议,如果您下载了该资源行为将被视为对《免责声明》全部内容的认可-> 联系客服 投诉资源
www.panoramacn.com资源全部来自互联网收集,仅供用于学习和交流,请勿用于商业用途。如有侵权、不妥之处,请联系站长并出示版权证明以便删除。 敬请谅解! 侵权删帖/违法举报/投稿等事物联系邮箱:2640602276@qq.com
未经允许不得转载:书荒源码源码网每日更新网站源码模板! » ES6笔记( 七 )- Symbol
关注我们小说电影免费看
关注我们,获取更多的全网素材资源,有趣有料!
120000+人已关注
分享到:
赞(0) 打赏

评论抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

您的打赏就是我分享的动力!

支付宝扫一扫打赏

微信扫一扫打赏