js中的symbol详解
目录
Symbol 类型
Symbol() 函数不可以 new
常用的内置符号 Symbol的工厂函数
1.Symbol.asyncIterator
2.Symbol.hasInstance
3.Symbol.isConcatSpreadable
4.Symbol.iterator
5.Symbol.match/replace/search/species/split
Symbol 类型
symbol的实例是唯一的不可变的, 用于确保对象的属性不重复
使用方式 : 调用 Symbol( 标识 ) 函数 返回一个符号
const a = Symbol('a');const obj = {[a]: 1};console.log(obj); // {Symbol(a): 1}
Symbol() 函数不可以 new
符号代表唯一的值, 但是我就想用一个符号呢 ?
通过 Symbol.for () 创建一个全局符号
const a = Symbol('a');const b = Symbol.for('b');const b2 = Symbol.for('b');const obj = {[a]: 1,[b]: 2,[b2]: 3};console.log(b === b2); // trueconsole.log(obj); // {Symbol(a): 1, Symbol(b): 3}// key通过覆盖替换 不必疑惑// b 和 b2 指向同一个符号
通过 Symbol.keyFor () 查看全局符号 参数是全局符号 返回符号的描述
如果传的不是全局符号 返回undefined
如果传的不是符号 报错
const b = Symbol.for('b123');
console.log(Symbol.keyFor(b)); // b123
常用的内置符号 Symbol的工厂函数
1.Symbol.asyncIterator
此方法返回对象的默认的异步迭代器, 可由 for - await - of 使用
// for await of 会调用对象以[Symbol.asyncIterator]为键的函数 该函数返回异步的generator
class Foo {constructor(n) {this.n = n;this.i = 0;}async *[Symbol.asyncIterator]() {while (this.i < this.n) {yield Promise.resolve(this.i++);}}}
async function fn() {const p = new Foo(5);for await (const x of p) {console.log(x);}}fn() // 0 1 2 3 4
2.Symbol.hasInstance
该方法判断一个对象是不是构造函数的实例 , 由 instanceof 使用 , 也就是说 instanceof 检测数据类型时的原理就是调用了 Symbol.hasInstance
这个属性被定义在 Function 上 所以函数和类都有 Symbol.hasInstance 方法
class Foo {static [Symbol.hasInstance]() {return false}}const demo = new Foo()console.log(Foo[Symbol.hasInstance](demo)); // falseconsole.log(demo instanceof Foo); // false
// 之所以会使false 是因为我重新定义了 [Symbol.hasInstance]() 函数 默认情况下是true
3.Symbol.isConcatSpreadable
这个符号作为属性返回一个布尔值 , 决定拼接数组时是否展开 , 默认为true
let arr = [0];const arr1 = [1];arr1[Symbol.isConcatSpreadable] = true;const arr2 = [2];arr2[Symbol.isConcatSpreadable] = false;arr = arr.concat(arr1, arr2)console.log(arr); // [0, 1, Array(1)]
4.Symbol.iterator
此方法返回对象默认的迭代器 for of 循环时就会调用对象的 Symbol.iterator函数(返回一个迭代器对象)
class Foo {constructor(n) {this.n = n;this.i = 0;}*[Symbol.iterator]() {while (this.i < this.n) {yield this.i++;}}}async function fn() {const p = new Foo(5);for (const x of p) {console.log(x);}}fn()
5.Symbol.match/replace/search/species/split
Symbol允许我们自定义某些函数, 以改变函数原本的行为 .
接下来简单说明一下
match
match 方法返回字符串匹配正则表达式的结果
即使参数传入的不是正则表达式 也会调用 new RegExp('xxx') 转为正则表达式
原始的matchconst str = 'abcdefg';const reg = /b/;const res = str.match(reg);console.log(res); // ['b', index: 1, input: 'abcdefg', groups: undefined]
自定义的matchconst str = 'abcdefg';const a = {[Symbol.match](target) {console.log(target);return false}};const res = str.match(a);console.log(res); // false
replace
replace 方法传入的参数替换字符串匹配正则表达式的结果返回新的字符串
即使参数传入的不是正则表达式 也会调用 new RegExp('xxx') 转为正则表达式
原始的replacelet str = 'abcdefg';str = str.replace('abc', '111') // 等价于 str = str.replace(/abc/, '111')console.log(str); // '111defg'
自定义的replace// 自定义 replacelet str1 = '123';const target = [];target[Symbol.replace] = (...rest) => {return `${rest[1]}${rest[0]}`}console.dir(target);str1 = str1.replace(target, '333')console.log(str1); // 333123
search
search 方法传入的参数为目标字符中出现的位置 会调用参数的 Symbol.search 进行求值
即使参数传入的不是正则表达式 也会调用 new RegExp('xxx') 转为正则表达式
let str = 'abcdefg';const res = str.search('d');console.log(res); // 3// 自定义 search 方法const demo = {};demo[Symbol.search] = (target) => {return 5}console.log(str.search(demo)); 5// 执行原理 // 调用String.proptype.search() // 该方法调用正则表达式的[Symbol.search]console.log(String.prototype.search);console.log(RegExp.prototype[Symbol.search]);
species
如果你定义一个扩展数组类 那么这个类的实例对象默认是同时指向父类和Array这个构造函数
如果你想只返回Array替换掉他的父类 那么可以使用静态方法
// static get [Symbol.species]() {// return Array;// }class Arr extends Array { };class Arr1 extends Array {static get [Symbol.species]() {return Array;}};const d1 = new Arr()console.log(d1.concat([]) instanceof Arr); // trueconsole.log(d1 instanceof Array); // trueconst d2 = new Arr1()console.log(d2.concat([]) instanceof Arr1); // falseconsole.log(d2 instanceof Array); // true
split
split() 方法以指定字符串分割调用对象, 在此方法调用时会使用以 Symbol.split 为键的函数
const str = 'abcd'const res = str.split('') // 等价于 str.split(new RegExp(''))console.log(res); // ['a', 'b', 'c', 'd']// 自定义 splitconst reg = new RegExp('')reg[Symbol.split] = (target) => {return 123}const res1 = str.split(reg)console.log(res1); // 123
6.Symbol.toPrimitive
对象转成字符串会被 String 函数转化成 '[object Object]'
如果想对对象进行加减运算 , 你可以通过定义 Symbol.toPrimitive 来实现
const obj = {};console.log(1 + obj); // 1[object Object]console.log(1 - obj); // NaNconsole.log(String(obj)); // [object Object]obj[Symbol.toPrimitive] = (hint) => {switch (hint) {case 'string':return '1';case 'number':return 0;default:return 'none'}}console.log(1 + obj); // 1noneconsole.log(1 - obj); // 1console.log(String(obj)); // 1
7.Symbol.toStringTag
对象使用 toString 方法时 会使用 Symbol.toStringTag 的返回值作为数组中的第二项
我的理解就是 Symbol.toStringTag 方法可以改变(实例对象)的 toString 输出指定的构造函数
const obj1 = {}console.log(obj1.toString()); // [object Object]class P { }const obj2 = new P()console.log(obj2.toString()); // [object Object]obj2[Symbol.toStringTag] = 'P'console.log(obj2.toString()); // [object P]
8.Symbol.unscopables
在 with 语句中 访问的变量默认都会访问器参数对象的属性
使用 Symbol.unscopables 可以指定对象哪些属性不在with环境下生效
// 例如const obj = {a: 'a',b: 'b'}obj[Symbol.unscopables] = {b: true}with (obj) {console.log(a);console.log(b); // 报错 b is not defined}
js中的symbol详解相关推荐
- computed用发_Vue.js中computed使用详解
这次给大家带来Vue.js中computed使用详解,Vue.js中computed使用的注意事项有哪些,下面就是实战案例,一起来看一下. JS属性: JavaScript有一个特性是Object.d ...
- Js中apply方法详解说明
Js apply 方法 详解 我在一开始看到JavaScript的函数apply和call时,非常的模糊,看也看不懂,最近在网上看到一些文章对apply方法和call的一些示例,总算是看的有点眉目了, ...
- JS中this关键字详解
本文主要解释在JS里面this关键字的指向问题(在浏览器环境下). 阅读此文章,还需要心平气和的阅读完,相信一定会有所收获,我也会不定期的发布,分享一些文章,共同学习 首先,必须搞清楚在JS里面,函数 ...
- JS中函数式编程详解版(FunctionalProgramming,FP)
函数式编程详解 函数式编程的认识 函数式编程前置知识 函数是一等公民(First-class Function) 高阶函数 闭包 函数式编程基础 纯函数 lodash 模块 柯里化 函数组合 函子 函 ...
- JS中的showModelDialog详解和实例
1.<a href="#" οnclick="SeePic('${list.PATH}')"><font color="blue&q ...
- JavaScript面向对象(一)——JS OOP基础与JS 中This指向详解
前 言 学过程序语言的都知道,我们的程序语言进化是从"面向机器".到"面向过程".再到"面向对象"一步步的发展而来.类似于汇编语言这样的面 ...
- Vue.js-Day01-PM【事件绑定(事件传参、事件对象、传参+获取事件对象)、样式处理操作(模板、事件、属性绑定)、Tab切换(原生js实现、Vue.js实现)、js中的this详解关键字】
Vue.js实训[基础理论(5天)+项目实战(5天)]博客汇总表[详细笔记] 目 录 4.事件绑定 4.1.事件绑定(点击.双击.鼠标移动) 点击按钮-最简单的事件绑定(无参函数) 格式 点击按钮 ...
- 【JS中scrollHeight/Width详解(不加定位的情况下)】
scrollHeight和scrollWidth的详解 一. 内容块Y轴上没有超出的情况下 二.内容块Y轴上有超出的情况下 2.1 当 overflow-y: visible的情况 2.2 设置ove ...
- JS中Location使用详解
javascript中 location用于获取或设置窗体的URL,并且可以用于解析URL,是BOM中最重要的对象之一,下面我们就来详细探讨下Location对象的使用. javascript中loc ...
- 前端基础知识点:JS中的参数传递详解
JS语法中的传递参数,对于初学者是一个非常重要的概念.很多小伙伴在学习"值传递"和"引用传递"时,会有不少烦恼.今天我们就来通过各种姿势全方位剖析JS中的值传递 ...
最新文章
- laravel mysql sum查询并排行_必看!PHP常见面试题——MySQL篇(二)
- oracle数据泵数据库导出导入及定时备份
- 【转】 DOTA2中的伪随机及其lua实现
- workerman events.php,workerman安装event扩展的方法介绍
- docker 安装 vsftpd
- 00084_Map接口
- Leetcode--714. 买卖股票的最佳时间含手续费
- java xml date_W3C XML 模式时间数据类型与java Date进行转换
- [洪流学堂]Hololens开发高级篇1:凝视(Gaze)
- linux连接mysql_主机Navicat连接linux(虚拟机)的mysql数据库
- Python获取指定目录下文件数量及总大小
- 单片机(ISIS 7 Professional):简易LED警报灯代码项目
- uc看视频显示服务器有点忙,UC3软件常见问题处理方案
- 含8的数字的个数 (10分)
- 我的程序员成长之路——回顾自己三年的工作
- 01背包中背包装满和不装满
- wordpress搜索引擎蜘蛛统计插件SEO
- [HTML]入门小知识,列表?框架?表格?来吧。纯手工制作,满满都是智慧
- matlab试判断稳定性,MATLABsimulink稳定性分析时域分析
- 华硕ProArt 创16体验:全新交互+顶级屏幕 更匹配创作的笔记本