记录-Symbol学习笔记
这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助
Symbol是JavaScript中的原始数据类型之一,它表示一个唯一的、不可变的值,通常用作对象属性的键值。由于Symbol值是唯一的,因此可以防止对象属性被意外地覆盖或修改。以下是Symbol的方法和属性整理:
属性
Symbol.length
Symbol构造函数的length属性值为0。
示例代码:
console.log(Symbol.length); // 0
方法
Symbol.for()
Symbol.for()方法会根据给定的字符串key,返回一个已经存在的symbol值。如果不存在,则会创建一个新的Symbol值并将其注册到全局Symbol注册表中。
示例代码:
const symbol1 = Symbol.for('foo');
const symbol2 = Symbol.for('foo'); console.log(symbol1 === symbol2); // true
使用场景: 当我们需要使用一个全局唯一的Symbol值时,可以使用Symbol.for()方法来获取或创建该值。例如,在多个模块之间共享某个Symbol值时,我们可以使用Symbol.for()来确保获取到的Symbol值是唯一的。
Symbol.keyFor()
Symbol.keyFor()方法会返回一个已经存在的Symbol值的key。如果给定的Symbol值不存在于全局Symbol注册表中,则返回undefined。
示例代码:
const symbol1 = Symbol.for('foo');
const key1 = Symbol.keyFor(symbol1); const symbol2 = Symbol('bar');
const key2 = Symbol.keyFor(symbol2); console.log(key1); // 'foo'
console.log(key2); // undefined
使用场景: 当我们需要获取一个全局唯一的Symbol值的key时,可以使用Symbol.keyFor()方法。但需要注意的是,只有在该Symbol值被注册到全局Symbol注册表中时,才能使用Symbol.keyFor()方法获取到其key。
Symbol()
Symbol()函数会返回一个新的、唯一的Symbol值。可以使用可选参数description来为Symbol值添加一个描述信息。
示例代码:
const symbol1 = Symbol('foo');
const symbol2 = Symbol('foo'); console.log(symbol1 === symbol2); // false
使用场景: 当我们需要使用一个唯一的Symbol值时,可以使用Symbol()函数来创建该值。通常情况下,我们会将Symbol值用作对象属性的键值,以确保该属性不会被意外地覆盖或修改。
Symbol.prototype.toString()
Symbol.prototype.toString()方法会返回Symbol值的字符串表示形式,该表示形式包含Symbol()函数创建时指定的描述信息。
示例代码:
const symbol = Symbol('foo'); console.log(symbol.toString()); // 'Symbol(foo)'
使用场景: 当我们需要将一个Symbol值转换成字符串时,可以使用Symbol.prototype.toString()方法。
Symbol.prototype.valueOf()
Symbol.prototype.valueOf()方法会返回Symbol值本身。
示例代码:
const symbol = Symbol('foo'); console.log(symbol.valueOf()); // Symbol(foo)
使用场景: 当我们需要获取一个Symbol值本身时,可以使用Symbol.prototype.valueOf()方法。
Symbol.iterator
Symbol.iterator是一个预定义好的Symbol值,表示对象的默认迭代器方法。该方法返回一个迭代器对象,可以用于遍历该对象的所有可遍历属性。
示例代码:
const obj = { a: 1, b: 2 }; for (const key of Object.keys(obj)) {
console.log(key);
}
// Output:
// 'a'
// 'b' for (const key of Object.getOwnPropertyNames(obj)) {
console.log(key);
}
// Output:
// 'a'
// 'b' for (const key of Object.getOwnPropertySymbols(obj)) {
console.log(key);
}
// Output:
// No output obj[Symbol.iterator] = function* () {
for (const key of Object.keys(this)) {
yield key;
}
} for (const key of obj) {
console.log(key);
}
// Output:
// 'a'
// 'b'
使用场景: 当我们需要自定义一个对象的迭代行为时,可以通过定义Symbol.iterator属性来实现。例如,对于自定义的数据结构,我们可以定义它的Symbol.iterator方法以便能够使用for...of语句进行遍历。
Symbol.hasInstance
Symbol.hasInstance是一个预定义好的Symbol值,用于定义对象的 instanceof 操作符行为。当一个对象的原型链中存在Symbol.hasInstance方法时,该对象可以被instanceof运算符使用。
示例代码:
class Foo {
static [Symbol.hasInstance](obj) {
return obj instanceof Array;
}
} console.log([] instanceof Foo); // true
console.log({} instanceof Foo); // false
使用场景: 当我们需要自定义一个对象的 instanceof 行为时,可以通过定义Symbol.hasInstance方法来实现。
Symbol.isConcatSpreadable
Symbol.isConcatSpreadable是一个预定义好的Symbol值,用于定义对象在使用concat()方法时的展开行为。如果一个对象的Symbol.isConcatSpreadable属性为false,则在调用concat()方法时,该对象不会被展开。
示例代码:
const arr1 = [1, 2];
const arr2 = [3, 4];
const obj = { length: 2, 0: 5, 1: 6, [Symbol.isConcatSpreadable]: false }; console.log(arr1.concat(arr2)); // [1, 2, 3, 4]
console.log(arr1.concat(obj)); // [1, 2, { length: 2, 0: 5, 1: 6, [Symbol(Symbol.isConcatSpreadable)]: false }]
使用场景: 当我们需要自定义一个对象在使用concat()方法时的展开行为时,可以通过定义Symbol.isConcatSpreadable属性来实现。
Symbol.toPrimitive
Symbol.toPrimitive是一个预定义好的Symbol值,用于定义对象在被强制类型转换时的行为。如果一个对象定义了Symbol.toPrimitive方法,则在将该对象转换为原始值时,会调用该方法。
示例代码:
const obj = {
valueOf() {
return 1;
},
[Symbol.toPrimitive](hint) {
if (hint === 'number') {
return 2;
} else if (hint === 'string') {
return 'foo';
} else {
return 'default';
}
}
}; console.log(+obj); // 2
console.log(`${obj}`); // 'foo'
console.log(obj + ''); // 'default'
使用场景: 当我们需要自定义一个对象在被强制类型转换时的行为时,可以通过定义Symbol.toPrimitive方法来实现。
Symbol.toStringTag
Symbol.toStringTag是一个预定义好的Symbol值,用于定义对象在调用Object.prototype.toString()方法时返回的字符串。如果一个对象定义了Symbol.toStringTag属性,则在调用该对象的toString()方法时,会返回该属性对应的字符串。
示例代码:
class Foo {
get [Symbol.toStringTag]() {
return 'Bar';
}
} console.log(Object.prototype.toString.call(new Foo())); // '[object Bar]'
使用场景: 当我们需要自定义一个对象在调用Object.prototype.toString()方法时返回的字符串时,可以通过定义Symbol.toStringTag属性来实现。
Symbol.species
Symbol.species是一个预定义好的Symbol值,用于定义派生对象的构造函数。如果一个对象定义了Symbol.species属性,则在调用该对象的派生方法(如Array.prototype.map())时,返回的新对象会使用该属性指定的构造函数。
示例代码:
class MyArray extends Array {
static get [Symbol.species]() {
return Array;
}
} const myArr = new MyArray(1, 2, 3);
const arr = myArr.map(x => x * 2); console.log(arr instanceof MyArray); // false
console.log(arr instanceof Array); // true
使用场景: 当我们需要自定义一个派生对象的构造函数时,可以通过定义Symbol.species属性来实现。
Symbol.match
Symbol.match是一个预定义好的Symbol值,用于定义对象在调用String.prototype.match()方法时的行为。如果一个对象定义了Symbol.match方法,则在调用该对象的match()方法时,会调用该方法进行匹配。
示例代码:
class Foo {
[Symbol.match](str) {
return str.indexOf('foo') !== -1;
}
} console.log('foobar'.match(new Foo())); // true
console.log('barbaz'.match(new Foo())); // false
使用场景: 当我们需要自定义一个对象在调用String.prototype.match()方法时的行为时,可以通过定义Symbol.match方法来实现。
Symbol.replace
Symbol.replace是一个预定义好的Symbol值,用于定义对象在调用String.prototype.replace()方法时的行为。如果一个对象定义了Symbol.replace方法,则在调用该对象的replace()方法时,会调用该方法进行替换。
示例代码:
class Foo {
[Symbol.replace](str, replacement) {
return str.replace('foo', replacement);
}
} console.log('foobar'.replace(new Foo(), 'baz')); // 'bazbar'
console.log('barbaz'.replace(new Foo(), 'baz')); // 'barbaz'
使用场景: 当我们需要自定义一个对象在调用String.prototype.replace()方法时的行为时,可以通过定义Symbol.replace方法来实现。
Symbol.search
Symbol.search是一个预定义好的Symbol值,用于定义对象在调用String.prototype.search()方法时的行为。如果一个对象定义了Symbol.search
class Foo {
[Symbol.search](str) {
return str.indexOf('foo');
}
} console.log('foobar'.search(new Foo())); // 0
console.log('barbaz'.search(new Foo())); // -1
使用场景: 当我们需要自定义一个对象在调用String.prototype.search()方法时的行为时,可以通过定义Symbol.search方法来实现。
Symbol.split
Symbol.split是一个预定义好的Symbol值,用于定义对象在调用String.prototype.split()方法时的行为。如果一个对象定义了Symbol.split方法,则在调用该对象的split()方法时,会调用该方法进行分割。
示例代码:
class Foo {
[Symbol.split](str) {
return str.split(' ');
}
} console.log('foo bar baz'.split(new Foo())); // ['foo', 'bar', 'baz']
console.log('foobarbaz'.split(new Foo())); // ['foobarbaz']
使用场景: 当我们需要自定义一个对象在调用String.prototype.split()方法时的行为时,可以通过定义Symbol.split方法来实现。
Symbol.iterator
Symbol.iterator是一个预定义好的Symbol值,用于定义对象在被遍历时的行为。如果一个对象定义了Symbol.iterator方法,则可以使用for...of循环、扩展运算符等方式来遍历该对象。
示例代码:
class Foo {
constructor() {
this.items = ['foo', 'bar', 'baz'];
} *[Symbol.iterator]() {
for (const item of this.items) {
yield item;
}
}
} const foo = new Foo(); for (const item of foo) {
console.log(item);
} // 'foo'
// 'bar'
// 'baz'
使用场景: 当我们需要自定义一个对象在被遍历时的行为时,可以通过定义Symbol.iterator方法来实现。比如,我们可以通过实现Symbol.iterator方法来支持自定义数据结构的遍历。
Symbol.toPrimitive
Symbol.toPrimitive是一个预定义好的Symbol值,用于定义对象在被强制类型转换时的行为。如果一个对象定义了Symbol.toPrimitive方法,则可以通过调用该方法来进行强制类型转换。
示例代码:
const obj = {
valueOf() {
return 1;
},
[Symbol.toPrimitive](hint) {
if (hint === 'default') {
return 'default';
} else if (hint === 'number') {
return 2;
} else {
return 'foo';
}
}
}; console.log(+obj); // 2
console.log(`${obj}`); // 'foo'
console.log(obj + ''); // 'default'
使用场景: 当我们需要自定义一个对象在被强制类型转换时的行为时,可以通过定义Symbol.toPrimitive方法来实现。
Symbol.toStringTag
Symbol.toStringTag是一个预定义好的Symbol值,用于定义对象在调用Object.prototype.toString()方法时返回的字符串。如果一个对象定义了Symbol.toStringTag属性,则在调用该对象的toString()方法时,会返回该属性对应的字符串。
示例代码:
class Foo {
get [Symbol.toStringTag]() {
return 'Bar';
}
} console.log(Object.prototype.toString.call(new Foo())); // '[object Bar]'
使用场景: 当我们需要自定义一个对象在调用Object.prototype.toString()方法时返回的字符串时,可以通过定义Symbol.toStringTag属性来实现。这样做有助于我们更清晰地表示对象的类型。
Symbol.unscopables
Symbol.unscopables是一个预定义好的Symbol值,用于定义对象在使用with语句时的行为。如果一个对象定义了Symbol.unscopables属性,则在使用with语句时,该对象的指定属性将不会被绑定到with语句的环境中。
示例代码:
const obj = {
a: 1,
b: 2,
c: 3,
[Symbol.unscopables]: {
c: true
}
}; with (obj) {
console.log(a); // 1
console.log(b); // 2
console.log(c); // ReferenceError: c is not defined
}
使用场景: 由于with语句会带来一些安全性问题和性能问题,因此在实际开发中不建议使用。但是,如果确实需要使用with语句,可以通过定义Symbol.unscopables属性来避免某些属性被误绑定到with语句的环境中。
Symbol.hasInstance
Symbol.hasInstance是一个预定义好的Symbol值,用于定义对象在调用instanceof运算符时的行为。如果一个对象定义了Symbol.hasInstance方法,则在调用该对象的instanceof运算符时,会调用该方法来判断目标对象是否为该对象的实例。
示例代码:
class Foo {
static [Symbol.hasInstance](obj) {
return Array.isArray(obj);
}
} console.log([] instanceof Foo); // true
console.log({} instanceof Foo); // false
使用场景: 当我们需要自定义一个对象在调用instanceof运算符时的行为时,可以通过定义Symbol.hasInstance方法来实现。比如,我们可以通过实现Symbol.hasInstance方法来支持自定义数据类型的判断。
总结
Symbol是ES6中新增的一种基本数据类型,用于表示独一无二的值。Symbol值在语言层面上解决了属性名冲突的问题,可以作为对象的属性名使用,并且不会被意外覆盖。除此之外,Symbol还具有以下特点:
- Symbol值是唯一的,每个Symbol值都是独一无二的,即使是通过相同的描述字符串创建的Symbol值,也不会相等;
- Symbol值可以作为对象的属性名使用,并且不会被意外覆盖;
- Symbol值可以作为私有属性来使用,因为无法通过对象外部访问对象中的Symbol属性;
- Symbol值可以被用作常量,因为它们是唯一的;
- Symbol值可以用于定义迭代器、类型转换规则、私有属性、元编程等高级功能。
在使用Symbol时需要注意以下几点:
- Symbol值不能使用new运算符创建;
- Symbol值可以通过描述字符串来创建,但是描述字符串并不是Symbol值的唯一标识符;
- Symbol属性在使用时需要用[]来访问,不能使用.运算符;
- 同一对象中的多个Symbol属性是独立的,它们之间不会互相影响。
总之,Symbol是一个非常有用的数据类型,在JavaScript中具有非常广泛的应用。使用Symbol可以有效地避免属性名冲突问题,并且可以为对象提供一些高级功能。熟练掌握Symbol,有助于我们写出更加健壮、高效和可维护的JavaScript代码。
本文转载于:
https://juejin.cn/post/7226193000496463928
如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。
记录-Symbol学习笔记的更多相关文章
- Linux 常用命令记录(学习笔记)
不同机器间文件传输(转自:http://www.zhimengzhe.com/mac/323324.html) scp是什么? scp是secure copy的简写,用于在Linux下进行远程拷贝文件 ...
- Vue2.0个人记录的学习笔记【待续】
一.Vue实例对象 我们构造一个实例对象 需要new一个Vue var my = new Vue({ el:‘#app’ ,[ app是装载的位置] template: ‘<div>< ...
- DirectX Graphics Infrastructure(DXGI):最佳范例 学习笔记
今天要学习的这篇文章写的算是比较早的了,大概在DX11时代就写好了,当时龙书11版看得很潦草,并没有注意这篇文章,现在看12,觉得是跳不过去的一篇文章,地址如下: https://msdn.micro ...
- 初学者的python学习笔记1
推荐一段时间闲的蛋疼,总觉得再堕落下去不太好,便捡起了之前一直想学而没有学的python,以此记录一下学习笔记,同时亦是督促和复习. 学习51cto上的<2016最新Python开发基础课程-2 ...
- SQLServer学习笔记系列4
一.写在前面的话 好多天没有记录sql学习笔记了,要坚持下去,坚信每一点的进步都是为在积蓄力量.今天看到一幅图,特此分享出来. 通过这幅图,我看到的是每人站在自己的角度看问题,感受是不一样的,就如同学 ...
- MVC学习笔记索引帖
[MVC学习笔记]1.项目结构搭建及单个类在各个层次中的实现 [MVC学习笔记]2.使用T4模板生成其他类的具体实现 [MVC学习笔记]3.使用Spring.Net应用IOC(依赖倒置) [MVC学习 ...
- .NET学习笔记(1)— C#学习路线图
目录 一:引言 二:.NET技术体系 三:常用工具汇总 四:学习资源汇总 五:书籍推荐 六:关于阅读技术书籍的经验 七:总结 一:引言 因为工作调整,从PHP开发零基础转型到.NET开发,前期没有 ...
- Jade学习笔记
初学nodejs,折腾过用handlebars做模板,后来隔了一段重新学习,用了jade,真心简洁……记录一些学习笔记,以备复习. jade是基于缩进的,所以tab与space不能混用: 属性的设置: ...
- Postman使用教程学习笔记
刚加入网页测试行列,最近在学习POSTman的使用教程,记录下学习笔记. Postman是一款功能强大的网页调试与发送网页HTTP请求的Chrome插件.当开发人员需要调试一个网页是否运行正常,并不是 ...
- Asp.net MVC4高级编程学习笔记-视图学习第一课20171009
首先解释下:本文只是对Asp.net MVC4高级编程这本书学习记录的学习笔记,书本内容感觉挺简单的,但学习容易忘记,因此在边看的同时边作下了笔记,可能其它朋友看的话没有情境和逻辑顺序还请谅解! 一. ...
随机推荐
- win10远程桌面连接,使用正确的用户名和密码仍然不能成功连接
最近笔记本重置后,台式使用"远程桌面连接"远程笔记本失败了,总是提示"登录没有成功". 开始自查:win10专业版,允许远程的相关设置也都开了,连接的ip正确, ...
- C++ 单例模式以及内存管理
引用: https://zhuanlan.zhihu.com/p/37469260 https://www.cnblogs.com/xiaolincoding/p/11437231.html http ...
- NC21125 践踏
题目链接 题目 题目描述 首先给定一个定值k,支持如下操作(在数轴上) 加入一条线段[l,r] 删除一条已经存在的线段 给定x,问有多少个区间包含x+kt,其中t是一个整数变量,即t ∈ Z 比如说当 ...
- NC16758 [NOIP2000]单词接龙
题目链接 题目 题目描述 单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母,要求出以这个字母开头的最长的"龙"(每个单词都最多在&quo ...
- Java官方文档
https://www.oracle.com/java/technologies/ https://www.oracle.com/java/technologies/downloads/archive ...
- Swoole从入门到入土(2)——TCP服务器[初步接触]
我们知道Swoole弥补了PHP没办法实现长连接的短板,在接下来的话题中,我们会从TCP服务器.HTTP服务器.WebSocket服务器.协程.管道.中间件等话题,一个个进行讨论. 1.开篇 我们以S ...
- 《深入理解Java虚拟机》(六) 调优策略 -- 笔记
目录 一.操作文档类功能,大量大对象直接进入老年代 问题现象 解决方法 通过单一Java虚拟机管理大量的内存 同一台服务器上部署若干Java虚拟机 二.异步请求大量累积 三.排查问题 排查问题: 可能 ...
- 理解[].forEach.call()并说明为什么要使用[].forEach.call()
[].forEach.call(elems, callback) 相当于: Array.prototype.forEach.call(elems, callback) 又相当于: function(e ...
- 项目实战:Qt+FFmpeg录屏应用(支持帧率、清晰度设置)
若该文为原创文章,转载请注明原文出处本文章博客地址:https://blog.csdn.net/qq21497936/article/details/109827936各位读者,知识无穷而人力有穷,要 ...
- sql题目---day39
# 1.查询所有的课程的名称以及对应的任课老师姓名 #where select teacher.tname,course.cname from teacher,course where course. ...