日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

js中的symbol详解

發(fā)布時間:2023/12/16 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 js中的symbol详解 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

目錄

Symbol 類型

Symbol() 函數(shù)不可以 new

常用的內(nèi)置符號 Symbol的工廠函數(shù)

1.Symbol.asyncIterator

2.Symbol.hasInstance

3.Symbol.isConcatSpreadable

4.Symbol.iterator

5.Symbol.match/replace/search/species/split


Symbol 類型

symbol的實例是唯一的不可變的, 用于確保對象的屬性不重復

使用方式 : 調(diào)用 Symbol( 標識 ) 函數(shù) 返回一個符號

? ?const a = Symbol('a');const obj = {[a]: 1};console.log(obj); ?// {Symbol(a): 1}

Symbol() 函數(shù)不可以 new

符號代表唯一的值, 但是我就想用一個符號呢 ?

通過 Symbol.for () 創(chuàng)建一個全局符號

? ?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 () 查看全局符號 參數(shù)是全局符號 返回符號的描述

如果傳的不是全局符號 返回undefined

如果傳的不是符號 報錯

const b = Symbol.for('b123'); console.log(Symbol.keyFor(b)); // b123

常用的內(nèi)置符號 Symbol的工廠函數(shù)

1.Symbol.asyncIterator

此方法返回對象的默認的異步迭代器, 可由 for - await - of 使用

// for await of 會調(diào)用對象以[Symbol.asyncIterator]為鍵的函數(shù) 該函數(shù)返回異步的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

該方法判斷一個對象是不是構造函數(shù)的實例 , 由 instanceof 使用 , 也就是說 instanceof 檢測數(shù)據(jù)類型時的原理就是調(diào)用了 Symbol.hasInstance

這個屬性被定義在 Function 上 所以函數(shù)和類都有 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]() 函數(shù) ? 默認情況下是true

3.Symbol.isConcatSpreadable

這個符號作為屬性返回一個布爾值 , 決定拼接數(shù)組時是否展開 , 默認為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 循環(huán)時就會調(diào)用對象的 Symbol.iterator函數(shù)(返回一個迭代器對象)

? ?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允許我們自定義某些函數(shù), 以改變函數(shù)原本的行為 .

接下來簡單說明一下

match

match 方法返回字符串匹配正則表達式的結果
即使參數(shù)傳入的不是正則表達式 也會調(diào)用 new RegExp('xxx') 轉(zhuǎn)為正則表達式

原始的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 方法傳入的參數(shù)替換字符串匹配正則表達式的結果返回新的字符串
即使參數(shù)傳入的不是正則表達式 也會調(diào)用 new RegExp('xxx') 轉(zhuǎn)為正則表達式

原始的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 方法傳入的參數(shù)為目標字符中出現(xiàn)的位置 ?會調(diào)用參數(shù)的 Symbol.search 進行求值
即使參數(shù)傳入的不是正則表達式 也會調(diào)用 new RegExp('xxx') 轉(zhuǎn)為正則表達式

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// 執(zhí)行原理 ?// 調(diào)用String.proptype.search() // 該方法調(diào)用正則表達式的[Symbol.search]console.log(String.prototype.search);console.log(RegExp.prototype[Symbol.search]);

species

如果你定義一個擴展數(shù)組類 那么這個類的實例對象默認是同時指向父類和Array這個構造函數(shù)
如果你想只返回Array替換掉他的父類 ?那么可以使用靜態(tài)方法?

// 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() 方法以指定字符串分割調(diào)用對象, 在此方法調(diào)用時會使用以 Symbol.split 為鍵的函數(shù)

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

對象轉(zhuǎn)成字符串會被 String 函數(shù)轉(zhuǎn)化成 '[object Object]'
如果想對對象進行加減運算 , 你可以通過定義 Symbol.toPrimitive 來實現(xiàn)

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 的返回值作為數(shù)組中的第二項?
我的理解就是 Symbol.toStringTag 方法可以改變(實例對象)的 toString 輸出指定的構造函數(shù)

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 語句中 訪問的變量默認都會訪問器參數(shù)對象的屬性?
?使用 Symbol.unscopables 可以指定對象哪些屬性不在with環(huán)境下生效

? ?// 例如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详解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。