IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> Symbol的基本使用 -> 正文阅读

[JavaScript知识库]Symbol的基本使用

Symbol的介绍

????????ES6引入了一种新的原始数据类型Symbol,表示独一无二的值。它是Javascript语言的第七种数据类型。

????????ES5对象属性名都是字符串,这容易造成属性名的冲突。为了解决这个问题引入了Symbol类型来解决命名冲突的问题。

????????Symbol值通过Symbol函数生成,也就是说,对象的属性名现在可以有两种形类型,一种是原来就有的字符串,另一种就是新增的Symbol类型。

Symbol的特点

  1. Symbol的值是唯一的,用来解决命名冲突的问题
  2. Symbol值不能与其他数据进行运算
  3. Symbol定义的对象属性不能使用for.in循环遍历,但是可以使用Reflect.ownkeys来获取对象的所有键名?

认识Symbol

?Symobol函数可以接受一个字符串作为参数,用来区分或者描述Symbol实例。

// 创建Symbol
let x = Symbol('abc')
let y = Symbol('123')
console.log(x, y);   // Symbol(abc) Symbol(123)

如果Symbol的参数传递的是一个对象,那么它内部会调用toString方法将对象转为字符串,在生成一个Symbol值。

// 参数传递对象
let a = Symbol({a: "a"})
console.log(a);     // Symbol([object Object])

相同参数创建出来的Symbol值是不相等的

// 相同参数不相等
let b = Symbol("1");
let c = Symbol("1");
console.log(b === c)   // false
let d = Symbol();
let e = Symbol();
console.log(d === e)   // false

Symbol的值不能与其他类型的值进行运算,如果进行运算会报错。

// 不能与其他类型的值进行运算
let n = Symbol("hello")
console.log(n + "world");  // Uncaught TypeError: Cannot convert a Symbol value to a string

Symbol可以显示转为字符串。

// Symbol显示转为字符串
let f = Symbol("hello wrold")
console.log(f.toString());    // Symbol(hello wrold)
console.log(typeof f.toString());    // string

Symbol也可以转为Boolean值

// Symbol也可以转为Boolean值
let g = Symbol("hello wrold")
console.log(Boolean(g));   // true

Symbol作为对象的属性名

????????前面我们说到每一个Symbol的值都是不相等的,所以我们可以将Symbol的值作为对象的属性名来使用,这样就能保证不会出现同名属性,防止属性被覆盖或者改写。

// 将Symbol作为对象的属性名使用
let sym = Symbol('sym'),
    sym1 = Symbol('sym1'),
    sym2 = Symbol('sym2');
const obj = {
    [sym]: "hello",
}
obj[sym1] = "world"
Object.defineProperty(obj, sym2, {value: "!!!!"})
console.log(obj);  // {Symbol(sym): 'hello', Symbol(sym1): 'world', Symbol(sym2): '!!!!'}
console.log(obj[sym], obj[sym1] ,obj[sym2]);    // hello world !!!!
const fun = Symbol('fun');
const obj1 = {
    [fun] () {
        console.log('hello world!');
    }
}
obj1[fun]()  //hello world!

Symbol属性名的遍历

????????Symbol 作为属性名,该属性不会出现在for in、for of循环中,也不会被Object.keys()、Object.getOwnPropertyNames()返回。但是它也不是私有属性,有一个Object.getOwnPropertySymbols()方法可以获指定对象的所有Symbol属性名。

????????Object.getOwnPropertySymbols()方法返回的是一个数组,成员是当前对象所有用作属性名的Symbol值

????????Reflect.ownKeys()方法返回所有类型的键名,包括常规键名和Symbol键名。

const a = Symbol('a')
const b = Symbol('b')
const obj = {
    a: 'a',
    b: 'b',
    [a]: 'a',
    [b]: 'b'
}
// // 返回当前对象所有用作属性名的Symbol值
const objSymbols = Object.getOwnPropertySymbols(obj)
console.log(objSymbols);   // [Symbol(a), Symbol(b)]
// 返回对象内所有类型的键名
const objSymbols1 = Reflect.ownKeys(obj)
console.log(objSymbols1);   // ['a', 'b', Symbol(a), Symbol(b)]

Symbol.for() 、Symbol.keyFor()

????????有时候我们想要使用同一个Symbol值,Symbol.keyFor()方法可以做到这一点。它接收一个字符串参数,让后搜索有没有以该参数作为名称的Symbol值,如果有,就返回这个Symbol值,否则就新建一个以该字符串命名的Symbol值。

// 同样参数使用Symbol.for方法生成的值相同
let sym = Symbol.for('a');
let sym1 = Symbol.for('a');
console.log(sym === sym1);    // true

????????Symbol.for()和Symbol()这两种写法都会生成新的Symbol,它们的区别是,前者会被登记在全局环境中供搜索,而后者不会Symbol.for(),不会在每次调用时都返回一个新的Symbol类型的值,而是先检查给定的key是否已经存在,如果不存在就会返回一个新值。

Symbol.keyFor()方法返回一个已登记的Symbol类型值的key

let sym = Symbol.for('a');
let sym1 = Symbol('a');
console.log(Symbol.keyFor(sym));   // 'a'
console.log(Symbol.keyFor(sym1));  // undefined

sym1属于为登记的Symbol值,所以返回undefined

注意:Symbol.for()方法为Symbol方法登记的名字是全局的。

内置的Symbol

????????除了定义自己使用的 Symbol 值以外,ES6 还提供了 11 个内置的 Symbol 值,指向语言内部使用的方法。

? ? ? ? 以下属性不一一举例说明了,如果需要详细示例请看ECMAScript 6 标准入门icon-default.png?t=L9C2https://es6.ruanyifeng.com/#docs/symbol

Symbol.hasInstance

????????对象的Symbol.hasInstance属性,指向一个内部方法。当其他对象使用instanceof运算符,判断是否为该对象的实例时,会调用这个方法。比如,foo instanceof Foo在语言内部,实际调用的是Foo[Symbol.hasInstance](foo)

class MyClass {
  [Symbol.hasInstance](foo) {
    return foo instanceof Array;
  }
}
[1, 2, 3] instanceof new MyClass() // true

????????上面代码中,MyClass是一个类,new MyClass()会返回一个实例。该实例的Symbol.hasInstance方法,会在进行instanceof运算时自动调用,判断左侧的运算子是否为Array的实例。

Symbol.isConcatSpreadable

????????对象的Symbol.isConcatSpreadable属性等于一个布尔值,表示该对象用于Array.prototype.concat()时,是否可以展开。

Symbol.species

对象的Symbol.species属性,指向一个构造函数。创建造衍生对象时,会使用该属性。

?

Symbol.match

对象的Symbol.match属性,指向一个函数。当执行str.match(myObject)时,如果该属性存在,会调用它,返回该方法的返回值。

Symbol.replace

对象的Symbol.replace属性,指向一个方法,当该对象被String.prototype.replace方法调用时,会返回该方法的返回值。

Symbol.search

对象的Symbol.search属性,指向一个方法,当该对象被String.prototype.search方法调用时,会返回该方法的返回值。

Symbol.split

对象的Symbol.split属性,指向一个方法,当该对象被String.prototype.split方法调用时,会返回该方法的返回值。

Symbol.iterator

对象的Symbol.iterator属性,指向该对象的默认遍历器方法。

Symbol.toPrimitive

对象的Symbol.toPrimitive属性,指向一个方法。该对象被转为原始类型的值时,会调用这个方法,返回该对象对应的原始类型值。

Symbol.toPrimitive被调用时,会接受一个字符串参数,表示当前运算的模式,一共有三种模式。

  • Number:该场合需要转成数值
  • String:该场合需要转成字符串
  • Default:该场合可以转成数值,也可以转成字符串

Symbol.toStringTag

对象的Symbol.toStringTag属性,指向一个方法。在该对象上面调用Object.prototype.toString方法时,如果这个属性存在,它的返回值会出现在toString方法返回的字符串之中,表示对象的类型。也就是说,这个属性可以用来定制[object Object][object Array]object后面的那个字符串。

Symbol.unscopables

对象的Symbol.unscopables属性,指向一个对象。该对象指定了使用with关键字时,哪些属性会被with环境排除。

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2021-10-16 19:33:27  更:2021-10-16 19:36:01 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/20 16:26:37-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码