深入理解ES6之《Symbol》

news/2025/3/22 2:09:58

创建Symbol及辨别方法

Symbol是原始值,因此调用new Symbol会导致程序抛出错误

let firstName = Symbol()
let person = {}
person[firstName] = "angela"
console.log(person[firstName])

使用typeof来辨别其类型

let symbol=Symbol('this is test description')
console.log(typeof symbol)//symbol

Symbol可用于计算对象字面量属性名、Object.defineProperty、Object.defineProperties

如果想创建一个共享的Symbol,可使用Symbol.for方法

let uid = Symbol.for('uid')
let object = {[uid]: '12345'
}
console.log(object[uid])//12345
console.log(uid)//Symbol(uid)
let uid2 = Symbol.for('uid')
console.log(uid === uid2)//true
console.log(object[uid2])//12345
console.log(uid2)//Symbol(uid)

Symbol.keyFor方法在Symbol全局注册表中检索与Symbol有关的键

let uid = Symbol.for('uid')
console.log(Symbol.keyFor(uid))//uid
let uid2 = Symbol.for('uid')
console.log(Symbol.keyFor(uid2))//uid
let uid3=Symbol('uid')
console.log(Symbol.keyFor(uid3))//undefined

Symbol全局注册表是一个类似全局作用域的共享环境,也就是说你不能假设目前环境中存在哪些键

Symbol与类型强制转换

不能将Symbol强制转换成数字类型,Symbol也不可以被转换成字符串

let uid = Symbol.for('uid')
let desc = uid + ""//报错 Uncaught TypeError: Cannot convert a Symbol value to a string
let uid = Symbol.for('uid')
let desc = uid / 1//报错  Uncaught TypeError: Cannot convert a Symbol value to a number

但是却可以像下面这样使用

let uid = Symbol.for('uid')
let desc = String(uid)
console.log(desc)//Symbol(uid)

Symbol属性检索

Object.getOwnPropertySymbols

let uid = Symbol.for('uid')
let object = {[uid]: '12345'
}
let symbols=Object.getOwnPropertySymbols(object)

Symbol.hasInstance

Symbol.hasInstance只接受一个参数,即要检查的值
每个函数都有Symbol.hasInstance方法,用于确定对象是否为函数实例,该方法在Function.prototype中定义,该方法被定义不为可写、不可配置、不可枚举

let obj = []
//obj instanceof Array //下面一句代码与此句功能等价
Array[Symbol.hasInstance](obj)//true 

我们可以通过Object.defineProperty方法改写一个不可写属性
所以其实可以重写所有内建函数(如Date和Error)默认的Symbol.hasInstance属性

function SpecialNumber() { }
Object.defineProperty(SpecialNumber, Symbol.hasInstance, {value: function (v) {return (v instanceof Number) && (v >= 1 && v <= 100)}
})
var two = new Number(2),zero = new Number(0);
console.log(two instanceof SpecialNumber)//true
console.log(zero instanceof SpecialNumber)//false

Symbol.isConcatSpreadable

Symbol.isConcatSpreadable属性值为true表明属性值应当作为独立元素添加到数组中

let c1 = ['red', 'green'],c2 = c1.concat(['blue', 'black'], 'yellow')
console.log(c2)//["red", "green", "blue", "black", "yellow"]

为什么上面一段代码结果是["red", "green", "blue", "black", "yellow"]而不是["red", "green", ["blue", "black"], "yellow"]?
图片描述
如果把上面的代码稍微改一下,结果就完全不一样了

let collection = {0: 'hello',1: 'world',2: 'demo',3: 'test',[Symbol.isConcatSpreadable]: true,length: 4
}
let msg = ['Hi'].concat(collection)
console.log(msg)//["Hi", "hello", "world", "demo", "test"]

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

let hasLenOf10 = {[Symbol.match](v) {return v.length === 10 ? [v.substring(0, 10)] : null},[Symbol.replace](v, replacement) {return v.length === 10 ? replacement + v.substring(10) : v;},[Symbol.search](v) {return v.length === 10 ? 0 : -1},[Symbol.split](v) {return v.length === 10 ? ["", ""] : [v]}
}
let msg1 = 'Hello world',msg2 = 'Hello John';
console.log(msg1.match(hasLenOf10))//null
console.log(msg2.match(hasLenOf10))//[Hello John]
console.log(msg1.replace(hasLenOf10))//Hello world
console.log(msg2.replace(hasLenOf10))//undefined
console.log(msg1.search(hasLenOf10))//-1
console.log(msg2.search(hasLenOf10))//0
console.log(msg1.split(hasLenOf10))//["Hello world"]
console.log(msg2.split(hasLenOf10))//["",""]

Symbol.toPrimitive

在执行特定操作时,经常会尝试将对象转换到相应的原始值
Symbol.toPrimitive被定义在每一个标准类型的原型上,并且规定了当对象被转换为原始值时应该执行的操作
每当执行类型转换总会调用Symbol.toPrimitive方法并传入一个值作为参数,这个值在规范中被称作类型提示hint,类型提示参数只有三种选择number、string、default

function Temperature(degree) {this.degree = degree
}
Temperature.prototype[Symbol.toPrimitive] = function (hint) {switch (hint) {case "string":return this.degree + '\u00b0';case "number":return this.degree;case "default":return this.degree + " degrees"}
}
var freezing = new Temperature(32)
console.log(freezing + "!")//32 degrees!
console.log(freezing / 2)//16
console.log(String(freezing))//32°

Symbol.toStringTag

以前判断一个对象的类型一般都是这样

function isArray(value) {return Object.prototype.toString.call(value) === "[object Array]"
}

ES6中我们可以自定义对象字符串标签

function Person(name) {this.name = name
}
Person.prototype[Symbol.toStringTag] = "Person"
Person.prototype.toString = function () {return this.name
}
var me = new Person('angela')
console.log(me.toString())//angela
console.log(Object.prototype.toString.call(me))//[object Person]

如果我们不重写toString方法,则me.toString返回的值就是[object Person]
我们可以给Person.prototype[Symbol.toStringTag]赋任意值,当然也可以修改原生对象的字符串标签


https://dhexx.cn/news/show-2159109.html

相关文章

Scala_ 类_可见性

WR R var T T val T F 缺省可见值 非var/val F F private var/val F F case类 default --- val 转载于:https://www.cnblogs.com/albertzz1987/p/7755607.html

C语言及程序设计初步例程-16 数据的输出

贺老师教学链接 C语言及程序设计初步 本课讲解 用printf函数输出 #include <stdio.h> int main() {printf("Hello World!\n"); printf("Welcome\nto\nBeijing!\n");return 0; } 用于整型数据的输出格式控制#include <stdio.h> int main(){pr…

判断是否 微信浏览器

var ua window.navigator.userAgent.toLowerCase(); if(ua.match(/MicroMessenger/i) micromessenger){/* 这是微信浏览器 */ }else{/* 不是微信浏览器 */ } 转载于:https://www.cnblogs.com/sunbeamy/p/10967745.html

[转] ReactNative Animated动画详解

http://web.jobbole.com/84962/ 首页所有文章JavaScriptHTML5CSS基础技术前端职场工具资源更多频道▼- 导航条 -首页所有文章JavaScriptHTML5CSS基础技术前端职场工具资源更多频道▼- iOS- Java- Android- Python伯乐在线 > WEB前端 - 伯乐在线 > 所有文章 > JavaScri…

leetcode Restore IP Addresses

2019独角兽企业重金招聘Python工程师标准>>> 将一个数字串转化成合法IP, DFS&#xff0c;注意一些细节 class Solution { public:vector<string> restoreIpAddresses(string s) {vector<string> ans;dfs(ans, s, "", 0, 0);return ans;}void…

公共平台服务治理与鉴权

问题 解决问题 鉴权 注册 管理 总结聊一聊最近了解的公司服务治理平台&#xff0c;主要是思想&#xff0c;理念&#xff0c;而不是一种技术或框架。整个平台设计&#xff0c;融入了OAUTH2认证&#xff0c;融入了微服务思想&#xff0c;帮助公司各系统在复杂的IT架构下&#xff…

MySQL 5.7.19 忘记密码 重置密码 配置文件my.ini示例 服务启动后停止 log配置

【参考】java 项目 存入mysql后 变问号 MySql 5.6 (X64) 解压版 1067错误与编码问题的解决方案 一、my.ini 的mysqld下添加 skip-grant-tables 二、重启mysql服务 net start mysqld 三、打开cmd cd C:\Program Files\MySQL\MySQL Server 5.7\bin  mysql  use mysql  设置…

Android SharedPreference的使用

在《Android 在内部存储读写文件》一文中&#xff0c;谈到了登录用户名和密码的方法&#xff0c;通过读取内存文件来实现&#xff0c;但是会出现问题&#xff0c;因为登录名和密码的形式通过username##password的形式&#xff0c;读取的时候以##为分割线&#xff0c;但是一旦用…

CSS3+Js制作的一款响应式导航条

今天制作了一个响应式导航条&#xff0c;能够自动随着不同的屏幕分辨率或浏览器窗口大小的不同而改变导航条的样式&#xff0c;这里主要用到的就是CSS3的Media Query。具体可以查看浅谈响应式布局这篇文章&#xff0c;这里就不花费大量的篇幅介绍了&#xff0c;主要看一下这个导…

php disallowed key characters,CI框架中出现Disallowed Key Characters

在搭建好CI框架后访问http://localhost/ci的时候总是出现Disallowed Key Characters.解决办法&#xff1a;在项目中搜索到包含“Disallowed Key Characters”的位置&#xff0c;一般在ci/system/core/Input.php中&#xff0c;大概在731行左右有如下代码&#xff1a;if ( ! preg…