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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

Symbol数据类型

發布時間:2023/12/16 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Symbol数据类型 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • 概述
  • 用法及注意事項
    • Symbol.for() 、 Symbol.keyFor()
    • 內置的 symbol 值
    • Symbol.isConcatSpreadable
    • Symbol.species
    • Symbol.match
    • Symbol.replace
    • Symbol.search
    • Symbol.split
    • Symbol.iterator
    • Symbol.toPrimitive
    • **Symbol.toStringTag**
  • 應用場景
    • 使用 symbol 作為對象的屬性名
    • 使用 symbol 定義常量

概述

symbol是一個ES6標準種新增的一種基本數據類型,在JavaScript中,共有七種基本數據類型:string、number、bigint、boolean、null、undefined、symbol。并且除了null和undefined之外,每個基本類型都有其包裝對象。

symbol 的值是通過 Symbol() 函數生成,每一個 symbol 的值都是唯一的,并且 symbol 類型的值可以作為對象的屬性標識符使用,這也是 symbol 類型設計的目的。
所以現在對象屬性名可以為兩種類型:一種就是原本的字符串類型,一種即為新增的 symbol 類型。凡是使用 symbol 命名的屬性都是獨一無二的,保證不與其他屬性名產生沖突。

用法及注意事項

  • 創建一個 symbol 的值需要使用 Symbol() 函數,而不能使用 new 命令。
let s = Symbol();typeof s // "symbol"
  • Symbol 值不是對象,所以不能添加屬性。基本上,它是一種類似于字符串的數據類型

    JavaScript 中大多數的數值都支持隱式轉換為字符串,但 symbol 不會轉換

let s1 = Symbol('sym'); alert(s1); // TypeError: Cannot convert a Symbol value to a string
  • symbol 也不能與其他類型的值進行運算
console.log('symbol is' + s1); // TypeError: Cannot convert a Symbol value to a string
  • 但是如果有必要,可以手動將 symbol 轉換成字符串
alert(s1.toString());
  • 或者獲得定義 symbol 時的描述:
alert(s1.description);

symbol 轉換為其他類型:

Boolean(s1); // true Number(s1); // TypeError: Cannot convert a Symbol value to a number parseInt(s1); // NaN
  • **Symbol 值不能與其他類型的值進行運算,會報錯
  • Symbol 值可以顯式轉為字符串,Symbol 值也可以轉為布爾值,但是不能轉為數值**
let sym = Symbol('My symbol');String(sym) // 'Symbol(My symbol)' sym.toString() // 'Symbol(My symbol)'let sym = Symbol(); Boolean(sym) // true !sym // falseif (sym) {// ... }

Symbol.for() 、 Symbol.keyFor()

如果我們要重復使用一個 symbol 時,可以用到 Symbol.for() 方法。Symbol.for() 方法接受一個字符串參數,會在全局中搜索有沒有以該參數命名的 symbol 的值,如果查找到就返回這個值。如果沒有查到則重新生成一個值,并將該值以參數名稱注冊到全局。

let s1 = Symbol.for('sym'); // 創建 let s2 = Symbol.for('sym'); // 查找 s1 === s2; // true

Symbol.for() 和 Symbol() 方法都會生成新的 symbol 類型的值,不同的是 Symbol.for() 方法會查找命名參數是否在全局中注冊過,如果注冊過的就不會創建新的值,而是會直接返回,所以我們可以使用到相同的 symbol 值。但使用 Symbol() 方法每次都會創建一個新的值,且不會注冊到全局。

Symbol.keyFor() 方法表示獲取一個 symbol 的值在全局中注冊的命名參數 key,只有使用 Symbol.for() 創建的值才會有注冊的命名參數,使用 Symbol() 生成的值則沒有:

let s4 = Symbol('sym'); let s5 = Symbol.for('sym'); Symbol.keyFor(s4); // undefined Symbol.keyFor(s5); // sym

注意使用 Symbol.for() 注冊的全局命名參數是真正意義上的全局,而不管是否運行在全局環境。

let iframe = document.createElement('iframe'); iframe.src = 'http://www.baidu.com'; document.body.append(iframe); iframe.contentWindow.Symbol.for('sym') === Symbol.for('sym'); // true

內置的 symbol 值

除了自定義 symbol 的值,ES6 還提供了 11 個內置的 symbol 值,指向語言內部使用的方法。

Symbol.hasInstance
Symbol.hasInstance 指向一個內部方法,當使用 instanceof 運算符時,判斷一個實例是否為某種類型時,會調用這個內部方法。

例如在調用:foo instanceof Foo 時,實際是調用 FooSymbol.hasInstance;

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

Symbol.isConcatSpreadable

該屬性的值是一個布爾型,表示當調用 Array.prototype.concat() 方法時,是否可以展開。
Symbol.isConcatSpreadable的默認值為undefined

例:

let arr = [1,2,3]; arr.concat([4,5]); // [1, 2, 3, 4, 5]

數組默認可以展開,當設置了 Symbol.isConcatSpreadable = false

let arr = [1,2,3]; arr[Symbol.isConcatSpreadable] = false; arr.concat([4,5]); // [Array(3), 4, 5]

Symbol.species

對象的 Symbol.species 屬性指向一個構造函數,在創建衍生對象可以更改構造函數指向。

例:

class MyArr extends Array{} let a = new MyArr(1,2,3); let b = a.filter(e => e >= 2); a instanceof MyArr; // true b instanceof MyArr; // true

其中變量 b 是變量 a 的衍生對象,變量 b 也是 MyArr 的實例,而通過設置 Symbol.species 可以更改這個衍生對象的構造函數:

class MyArr extends Array{static get [Symbol.species](){return Array;} } let a = new MyArr(1,2,3); let b = a.filter(e => e >= 2); a instanceof MyArr; // true b instanceof MyArr; // false

實際上,默認的 Symbol.species 屬性等同:

static get [Symbol.species]() {return this;

總之該屬性實在實例運行過程中,需要再次調用自身構造函數時,可以使用指定的構造函數。

Symbol.match

該屬性指向一個函數,當執行 str.match(object) 時,如果該屬性存在,會調用該屬性指向的方法:

let str = 'e'; class StrObj {[Symbol.match](string){return 'hello'.indexOf(string);} } str.match(new StrObj()); // 1 // 等同于 new StrObj()[Symbol.match](str); // 1

Symbol.replace

該屬性指向一個方法,當對象被 String.prototype.replace 方法調用時,會執行該方法:

String.prototype.replace(searchValue, replaceValue) // 等同于 searchValue[Symbol.replace](this, replaceValue)

Symbol.search

對象的 Symbol.search 屬性,指向一個方法,當該對象被String.prototype.search 方法調用時,會返回該方法的返回值。

String.prototype.search(regexp) // 等同于 regexp[Symbol.search](this)

Symbol.split

對象的 Symbol.split 屬性,指向一個方法,當該對象被 String.prototype.split 方法調用時,會返回該方法的返回值。

String.prototype.split(separator, limit) // 等同于 separator[Symbol.split](this, limit)

Symbol.iterator

對象的 Symbol.iterator 屬性,指向該對象的默認遍歷器方法。

const myIterable = {}; myIterable[Symbol.iterator] = function* () {yield 1;yield 2;yield 3; };[...myIterable] // [1, 2, 3]

Symbol.toPrimitive

對象的 Symbol.toPrimitive 屬性,指向一個方法。該對象被轉為原始類型的值時,會調用這個方法,返回該對象對應的原始類型值。

Symbol.toPrimitive 被調用時,會接受一個字符串參數,表示當前運算的模式,一共有三種模式:

Number:該場合需要轉成數值String:該場合需要轉成字符串Default:該場合可以轉成數值,也可以轉成字符串 let obj = {[Symbol.toPrimitive](hint) {switch (hint) {case 'number':return 123;case 'string':return 'str';case 'default':return 'default';default:throw new Error();}}};2 * obj // 2463 + obj // '3default'obj == 'default' // trueString(obj) // 'str'

Symbol.toStringTag

對象的 Symbol.toStringTag 屬性,指向一個方法。在該對象上面調用Object.prototype.toString 方法時,如果這個屬性存在,它的返回值會出現在toString方法返回的字符串之中,表示對象的類型。也就是說,這個屬性可以用來定制 [object Object] 或 [object Array] 中 object 后面的那個字符串。

// 例一 ({[Symbol.toStringTag]: 'Foo'}.toString()) // "[object Foo]"// 例二 class Collection {get [Symbol.toStringTag]() {return 'xxx';} } let x = new Collection(); Object.prototype.toString.call(x) // "[object xxx]"

Symbol.unscopables
對象的 Symbol.unscopables 屬性,指向一個對象。該對象指定了使用with關鍵字時,哪些屬性會被 with 環境排除。
即使用 Symbol.unscopables 指定的對象,在使用 with 語法塊時,不在當前作用域中尋找特定屬性,而是從外層作用域開始查找。

// 沒有 unscopables 時 class MyClass {foo() { return 1; } }var foo = function () { return 2; };with (MyClass.prototype) {foo(); // 1 }// 有 unscopables 時 class MyClass {foo() { return 1; }get [Symbol.unscopables]() {return { foo: true };} }var foo = function () { return 2; };with (MyClass.prototype) {foo(); // 2 }

應用場景

使用 symbol 作為對象的屬性名

由于每一個 symbol 的值都是不相同的,所以使用 symbol 作為屬性名可以保證不會出現同名屬性。防止某一個屬性被改寫覆蓋:

let s1 = Symbol(‘sym’); let obj = {undefined name: ‘test obj’, [s1]:this is symbol’ } obj[s1]; // this is symbol

**

  • 注意使用 symbol 作為對象的屬性名時,是無法通過 Object.keys() 和 for…in 來遍歷對象的屬性的

**

Object.keys(obj); // ["name"]for(let name in obj){console.log(name); // name }

因此,在將對象進行 JSON 轉換時: JSON.stringify() ,symbol 的屬性也會被排除:

JSON.stringify(obj); // "{"name":"test obj"}"

需要注意的是,使用 symbol 定義的屬性,還是公有的屬性,不是私有屬性。

使用 symbol 定義常量

  • 使用 symbol 定義的常量能保證常量的值都是不相等的。
const COLOR_RED = Symbol();const COLOR_GREEN = Symbol();function getComplement(color) {switch (color) {case COLOR_RED:return COLOR_GREEN;case COLOR_GREEN:return COLOR_RED;default:throw new Error('Undefined color');}}

總結

以上是生活随笔為你收集整理的Symbol数据类型的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。