記錄-Symbol學習筆記

来源:https://www.cnblogs.com/smileZAZ/archive/2023/05/05/17374841.html
-Advertisement-
Play Games

這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 Symbol是JavaScript中的原始數據類型之一,它表示一個唯一的、不可變的值,通常用作對象屬性的鍵值。由於Symbol值是唯一的,因此可以防止對象屬性被意外地覆蓋或修改。以下是Symbol的方法和屬性整理: 屬性 Symbol.l ...


這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助

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

如果對您有所幫助,歡迎您點個關註,我會定時更新技術文檔,大家一起討論學習,一起進步。

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 本文源碼部分基於內核 5.4 版本討論 在經過上篇文章 《從內核源碼看 slab 記憶體池的創建初始化流程》 的介紹之後,我們最終得到下麵這幅 slab cache 的完整架構圖: 本文筆者將帶大家繼續從內核源碼的角度繼續拆解 slab cache 的實現細節,接下來筆者會基於上面這幅 slab ca ...
  • 哈嘍大家好我是鹹魚,在《Linux 記憶體管理 pt.1》中我們學習了什麼是物理記憶體、虛擬記憶體,瞭解了記憶體映射、缺頁異常等內容 那麼今天我們來接著學習 Linux 記憶體管理中的多級頁表和大頁 多級頁表&大頁 在《Linux 記憶體管理 pt.1》中我們知道了內核為每個進程都維護了一張頁表,這張頁表用來記 ...
  • 在MySQL中,這幾個都是統計操作,很多人在使用的時候,都使用的是count(1),這有沒有問題?使用正確?達到了統計效果? 我們從效果和效率兩方面來分析下 執行效果 count(*) 包括了所有的列,在統計時不會忽略列值為null的數據count(1) 用1表示代碼行,在統計時不會忽略列值為nul ...
  • 4月20日,袋鼠雲成功舉行了以“數實融合,韌性生長”為主題的2023春季生長大會。會上重磅發佈了袋鼠雲生態伙伴計劃——“飛躍計劃2.0”,從商機、產品、聯合方案及數據業務服務層面,與合作伙伴強強聯手,共同打造數字化生態,同時在聯合營銷、渠道政策、賦能培訓、產品開放、技術服務、交付實施等方面全面升級夥 ...
  • 摘要:本文主要介紹GaussDB(DWS)網路流控能力,並對其管控效果進行驗證。 本文分享自華為雲社區《GaussDB(DWS)網路流控與管控效果》,作者:門前一棵葡萄樹。 上一篇博文GaussDB(DWS)網路調度與隔離管控能力,我們詳細介紹了GaussDB網路調度邏輯,並簡單介紹瞭如何應用網路隔 ...
  • 0. 前情提要 系統的某個用來上報數據的介面存在死鎖的問題。這個介面內部對多張表進行了Update操作,執行順序為A表、B表、C表、D表、A表。死鎖發生的SQL,一條是第一次更新A表的SQL,另一條是第二次更新A表的SQL。整個更新都處在一個事務內,理論上講,只要第一個Session開始執行事務,第 ...
  • Redis事務(Transaction)通過將多個Redis操作封裝為一個原子性的操作序列,確保在事務執行過程中,不會受到其他客戶端的干擾。從而在保證數據一致性的同時,協調併發,提高數據操作的效率和性能 ...
  • 如何優雅的將項目中的代碼,亦或是你的demo代碼展示到界面上?本文對使用簡單、便於維護且通用的解決方案,進行相關的對比和探究 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...