亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

vscode工具函數(shù)Symbol使用深入解析

 更新時間:2023年03月28日 15:18:21   作者:孟健  
這篇文章主要為大家介紹了vscode工具函數(shù)Symbol使用深入解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

什么是Symbol?

符號(Symbol)是JavaScript中的一個原始數(shù)據(jù)類型,是ECMAScript 6標準引入的新特性。符號是一種類似于字符串的數(shù)據(jù)類型,但與字符串不同的是,符號是唯一的并且不可變的。

Symbol的定義方法如下:

const mySymbol = Symbol('my symbol');

每次調(diào)用Symbol創(chuàng)建的值都是唯一的,即使對同一個參數(shù)調(diào)用兩遍Symbol它們的值還是不一樣的:

Symbol("foo") === Symbol("foo"); // false

js的第六種基本數(shù)據(jù)類型

Symbol出現(xiàn)之前,Javascript已經(jīng)有五種內(nèi)置的基本數(shù)據(jù)類型:

  • 布爾值(Boolean):表示真或假,只有兩個取值:true和false。
  • 數(shù)字(Number):表示整數(shù)或浮點數(shù),可以使用十進制、十六進制、八進制、科學計數(shù)法等多種表示方式。
  • 字符串(String):表示文本字符串,可以使用單引號、雙引號、反引號等方式表示。
  • 空值(Null):表示一個空值或不存在的對象。
  • 未定義(Undefined):表示一個未定義的值或未聲明的變量。

Symbol則作為第六種基本數(shù)據(jù)類型加入到語言中:

  • 符號(Symbol):表示唯一的、不可變的值,用于保護屬性名、實現(xiàn)私有屬性或方法等場景。

Symbol的起源

在JavaScript誕生之初,對象屬性只能使用字符串作為鍵,這導致了一些問題。例如,當兩個不同的對象試圖使用相同的字符串作為屬性名時,可能會導致屬性名沖突。此外,JavaScript中沒有一種簡單的方法來實現(xiàn)私有屬性或方法。

其實對于Symbol的追溯早在Lisp語言中就有體現(xiàn):

(setq x (intern "my-symbol"))

這里其實就是創(chuàng)建了一個名為my-symbol的符號對象,并將其賦值給變量x

另外,ES6引入Symbol其實離不開Ruby的身影,在Ruby中,可以使用冒號(:)來創(chuàng)建符號。冒號后面跟著符號的名稱,如:

:my_symbol

可以看到其實Ruby的語法更加簡潔,定義和使用都是用冒號區(qū)分:

person = {
  'name' => 'John',
  'age' => 30,
  :gender => 'Male'
}
puts person[:gender]  # 輸出:'Male'

所以,在這樣的需求背景下,ES6在首批特性中包含了Symbol也不足為奇了。

Symbol的基本知識

定義與使用

JavaScript中,可以使用Symbol()函數(shù)來創(chuàng)建一個符號,如下所示:

const mySymbol = Symbol();

Symbol函數(shù)可以接受一個描述性字符串作為參數(shù),用于標識符號的含義,如下所示:

const mySymbol = Symbol('my symbol');

需要注意的是,每個Symbol()函數(shù)調(diào)用都會返回一個唯一的符號,即使描述性字符串相同,它們也是不同的符號。

Symbol類型的值可以用作對象的屬性名,如下所示:

const mySymbol = Symbol('my symbol');
const myObject = {
  [mySymbol]: 'hello'
};
console.log(myObject[mySymbol]);  // 輸出:'hello'

在上面的代碼中,我們使用符號mySymbol作為對象myObject的屬性名,并將其值設(shè)置為'hello'。使用符號作為屬性名的好處是它們不會與其他屬性名沖突,并且對外不可見,因此可以用于實現(xiàn)私有屬性或方法等場景。

另外,JavaScript中的Symbol類型有兩個特殊的方法Symbol.for()Symbol.keyFor(),用于創(chuàng)建全局符號和獲取已經(jīng)存在的全局符號。

  • Symbol.for(): 用于創(chuàng)建或獲取一個全局符號,如果全局符號已經(jīng)存在,則返回已經(jīng)存在的符號,否則創(chuàng)建一個新的全局符號。例如:
const mySymbol = Symbol.for('my symbol');
const sameSymbol = Symbol.for('my symbol');
console.log(mySymbol === sameSymbol);  // 輸出:true

在上面的代碼中,我們使用Symbol.for()方法來創(chuàng)建一個全局符號'my symbol',并將其賦值給mySymbol變量。然后,我們再次使用Symbol.for()方法來獲取同一個全局符號,賦值給sameSymbol變量。由于全局符號已經(jīng)存在,因此sameSymbol變量的值等于mySymbol變量的值,輸出true。

Symbol的重要屬性

1. Symbol.iterator: 用于指定對象的默認迭代器,例如:

const myObject = {
  *[Symbol.iterator]() {
    yield 1;
    yield 2;
    yield 3;
  }
};
for (const value of myObject) {
  console.log(value);
}
// 輸出:1 2 3

在上面的代碼中,我們?yōu)?code>myObject對象設(shè)置了Symbol.iterator符號,并指定了一個生成器函數(shù)作為迭代器的實現(xiàn)。然后,我們可以使用for...of循環(huán)迭代myObject對象,并輸出其中的值。

2. Symbol.hasInstance: 用于定義一個對象是否為某個構(gòu)造函數(shù)的實例。

Symbol.hasInstance方法接受一個參數(shù),表示要檢查的對象。該方法需要返回一個布爾值,表示該對象是否為該構(gòu)造函數(shù)的實例。例如:

class MyClass {
  static [Symbol.hasInstance](obj) {
    return obj instanceof Array;
  }
}
console.log([] instanceof MyClass);  // 輸出:true
console.log({} instanceof MyClass);  // 輸出:false

在上面的代碼中,我們定義了一個MyClass類,并使用Symbol.hasInstance方法自定義了instanceof運算符的行為,使其檢查對象是否為數(shù)組。當檢查[]對象時,instanceof運算符返回true,因為[]是Array的實例;當檢查{}對象時,instanceof運算符返回false,因為{}不是Array的實例。

需要注意的是,Symbol.hasInstance方法是一個靜態(tài)方法,需要定義在構(gòu)造函數(shù)的靜態(tài)屬性中。另外,Symbol.hasInstance方法不能被繼承,因此子類需要重新定義該方法。

3. Symbol.toStringTag: 用于自定義對象的默認字符串描述。

當調(diào)用Object.prototype.toString()方法時,會使用該對象的Symbol.toStringTag屬性作為默認的字符串描述,例如:

class MyObject {
  get [Symbol.toStringTag]() {
    return 'MyObject';
  }
}
const obj = new MyObject();
console.log(Object.prototype.toString.call(obj));  // 輸出:'[object MyObject]'

在上面的代碼中,我們定義了一個MyObject類,并使用Symbol.toStringTag屬性自定義了該類的默認字符串描述。然后,我們創(chuàng)建了一個obj對象,并使用Object.prototype.toString()方法獲取其字符串描述,輸出'[object MyObject]'

需要注意的是,Symbol.toStringTag屬性只有在調(diào)用Object.prototype.toString()方法時才會生效,對其他方法沒有影響。另外,如果沒有定義Symbol.toStringTag屬性,則默認使用構(gòu)造函數(shù)的名稱作為字符串描述。

4. Symbol.asyncIterator: 用于指定對象的默認異步迭代器。

當使用for await...of循環(huán)迭代一個對象時,會調(diào)用該對象的Symbol.asyncIterator方法獲取異步迭代器。

Symbol.asyncIterator方法需要返回一個異步迭代器對象,該對象實現(xiàn)了next()方法,并返回一個Promise對象。當?shù)鞯浇Y(jié)束時,next()方法應(yīng)該返回一個Promise對象,該Promise對象的value屬性為undefined,done屬性為true

例如,下面的代碼演示了如何使用Symbol.asyncIterator屬性定義一個異步迭代器:

const myObject = {
  async *[Symbol.asyncIterator]() {
    yield Promise.resolve(1);
    yield Promise.resolve(2);
    yield Promise.resolve(3);
  }
};
(async function() {
  for await (const value of myObject) {
    console.log(value);
  }
})();
// 輸出:1 2 3

在上面的代碼中,我們?yōu)?code>myObject對象設(shè)置了Symbol.asyncIterator符號,并指定了一個異步生成器函數(shù)作為異步迭代器的實現(xiàn)。然后,我們使用for await...of循環(huán)迭代myObject對象,并輸出其中的值。

需要注意的是,使用Symbol.asyncIterator屬性定義的異步迭代器只能使用for await...of循環(huán)進行迭代,不能使用普通的for...of循環(huán)。此外,Symbol.asyncIterator屬性只有在支持異步迭代器的環(huán)境中才能使用,例如Node.js的版本必須在10.0.0以上才支持異步迭代器。

Symbol的實現(xiàn)原理

symbol作為基本數(shù)據(jù)類型實現(xiàn)比較簡單,在最新的v8代碼實現(xiàn)如下:

Symbol Factory::NewSymbolInternal(AllocationType allocation) {
  DCHECK(allocation != AllocationType::kYoung);
  // Statically ensure that it is safe to allocate symbols in paged spaces.
  STATIC_ASSERT(Symbol::kSize <= kMaxRegularHeapObjectSize);
  Symbol symbol = Symbol::cast(AllocateRawWithImmortalMap(
      Symbol::kSize, allocation, read_only_roots().symbol_map()));
  DisallowGarbageCollection no_gc;
  // Generate a random hash value.
  int hash = isolate()->GenerateIdentityHash(Name::kHashBitMask);
  symbol.set_raw_hash_field(Name::kIsNotIntegerIndexMask |
                            (hash << Name::kHashShift));
  symbol.set_description(read_only_roots().undefined_value(),
                         SKIP_WRITE_BARRIER);
  symbol.set_flags(0);
  DCHECK(!symbol.is_private());
  return symbol;
}

該函數(shù)使用AllocateRawWithImmortalMap()方法為新的Symbol對象分配內(nèi)存,并將其強制轉(zhuǎn)換為Symbol類型。接著,該函數(shù)使用DisallowGarbageCollection類禁用垃圾回收器,以確保不會在生成哈希值的過程中觸發(fā)垃圾回收。接下來,該函數(shù)使用GenerateIdentityHash()方法生成一個隨機的哈希值,并將其存儲在新的Symbol對象中。然后,該函數(shù)將Symbol對象的描述設(shè)置為undefined,并將其標志設(shè)置為0。最后,該函數(shù)返回新創(chuàng)建的Symbol對象。

所以使用hash來唯一標識一個symbol,在v8內(nèi)部還實現(xiàn)了symbol-table來實現(xiàn)Symbol.for的查找,本質(zhì)上也是一個哈希表。

為了簡單起見,我們用js來模擬一下Symbol的實現(xiàn):

const registry = {};
function createSymbol(description) {
  const symbol = Object.create(null);
  symbol.toString = () => `Symbol(${description || ''})`;
  Object.defineProperty(symbol, 'description', {
    value: description,
    writable: false,
    configurable: false,
    enumerable: false,
  });
  return symbol;
}
function Symbol(description) {
  if (typeof description !== 'undefined') {
    description = String(description);
  }
  if (registry[description]) {
    return registry[description];
  }
  const symbol = createSymbol(description);
  registry[description] = symbol;
  return symbol;
}
Symbol.for = function (key) {
  if (registry[key]) {
    return registry[key];
  }
  const symbol = createSymbol(key);
  registry[key] = symbol;
  return symbol;
};
Symbol.keyFor = function (symbol) {
  for (const key in registry) {
    if (registry.hasOwnProperty(key) && registry[key] === symbol) {
      return key;
    }
  }
};
export default Symbol;

我們使用一個全局對象registry來存儲Symbol對象及其描述符信息。createSymbol()函數(shù)用于創(chuàng)建新的Symbol對象,其中使用了Object.create()方法來創(chuàng)建一個沒有原型的對象,并通過定義toString()description屬性來實現(xiàn)Symbol對象的基本功能。Symbol()函數(shù)用于創(chuàng)建新的Symbol對象,它根據(jù)傳入的描述符信息從registry中查找Symbol對象,如果找到了則返回已有的Symbol對象,否則創(chuàng)建新的Symbol對象并添加到registry中。

Symbol的使用場景

SymbolVSCode的應(yīng)用其實不多,最新的代碼只有:

/**
 * Can be passed into the Delayed to defer using a microtask
 * */
export const MicrotaskDelay = Symbol('MicrotaskDelay');

在實際中,Symbol經(jīng)常被用于:

1. 唯一屬性鍵:Symbol可以作為對象屬性的鍵,避免屬性名沖突。

這在創(chuàng)建第三方庫或插件時非常有用,因為可以確保庫或插件的屬性不會與其他代碼意外沖突。

const uniqueKey = Symbol('uniqueKey');
const obj = {
  [uniqueKey]: 'This value is uniquely keyed'
};

2. 定義私有屬性(當然這一點現(xiàn)在ES規(guī)范已經(jīng)有更好的方式了)

使用Symbol可以在對象上創(chuàng)建"私有"屬性,它們不會被常規(guī)的屬性枚舉(如for...inObject.keys()JSON.stringify())包含在內(nèi)。這有助于保護對象內(nèi)部實現(xiàn)細節(jié)。

3. 內(nèi)置Symbol

JavaScript內(nèi)置了一些具有特定功能的Symbol。例如,Symbol.iterator可以定義對象的迭代行為,Symbol.toStringTag可以自定義Object.prototype.toString.call()方法的輸出。

4. 注冊全局Symbol

Symbol.for()方法允許在全局Symbol注冊表中創(chuàng)建或獲取Symbol。這對于跨多個地方或模塊使用相同的Symbol時非常有用。

const globalSymbol = Symbol.for('globalSymbol');
const sameGlobalSymbol = Symbol.for('globalSymbol');
console.log(globalSymbol === sameGlobalSymbol); // true

Symbol的發(fā)展

tc39上已經(jīng)有兩個關(guān)于Symbol的提案:

Symbols as WeakMap keys(Stage3)

Symbol作為一種新的數(shù)據(jù)類型,其功能和用途都比較有限,因此tc39Symbol的基礎(chǔ)上提出了一些新的提案,以擴展其功能和用途。其中一個比較重要的提案是Symbols as WeakMap keys,該提案已經(jīng)進入到Stage3階段。

WeakMap是一種新的集合類型,可以用于存儲對象和關(guān)聯(lián)的元數(shù)據(jù)。WeakMap的特點是鍵必須是對象,值可以是任意類型。WeakMap的另一個特點是,當鍵對象不再被引用時,WeakMap會自動刪除該鍵值對,以避免內(nèi)存泄漏。

Symbols as WeakMap keys提案的目的是將Symbol作為WeakMap的鍵。這樣,就可以在不影響WeakMap的自動垃圾回收機制的情況下,將Symbol作為對象的元數(shù)據(jù)來使用。

const weak = new WeakMap();
// Pun not intended: being a symbol makes it become a more symbolic key
const key = Symbol('my ref');
const someObject = { /* data data data */ };
weak.set(key, someObject);

Symbol Predicates Proposal(Stage2)

這是另一個關(guān)于Symbol的提案,添加了以下判斷方法:Symbol.isRegistered(symbol)Symbol.isWellKnown(symbol)

其實對于庫作者而言,了解更多關(guān)于Symbol的信息是很重要的。根據(jù)使用情況,了解一個Symbol是否真正唯一、可偽造(已注冊)或跨域共享(眾所周知)可能非常關(guān)鍵。例如,將Symbol用作WeakMap鍵需要確保Symbol未被注冊。該提案處于第二階段,正在受到JavaScript社區(qū)的廣泛關(guān)注。如果被采納,它將為Symbol的應(yīng)用帶來更多的靈活性。

function isWeakMapKey(key) {
  switch (typeof key) {
    case "object":
      return key !== null;
    case "function":
      return true;
    case "symbol":
      return !Symbol.isRegistered(sym);
  }
  return false;
}
isWeakMapKey({}); // true
isWeakMapKey(Symbol()); // true
isWeakMapKey("foo"); // false
isWeakMapKey(Symbol.for("foo")); // false
isWeakMapKey(Symbol.asyncIterator); // true

您還可以檢查是否獲得了真正唯一的Symbol

const isUniqueSymbol = sym => typeof sym === "symbol" && !(Symbol.isRegistered(sym) || Symbol.isWellKnown(sym));
isUniqueSymbol(Symbol()); // true
isUniqueSymbol(Symbol.for("foo")); // false
isUniqueSymbol(Symbol.asyncIterator); // false
isUniqueSymbol({}); // false

小結(jié)

本文介紹了JavaScript中的Symbol類型,包括Symbol的創(chuàng)建、使用場景以及實現(xiàn)原理。Symbol是一種新的基本數(shù)據(jù)類型,用于表示唯一標識符。與字符串和數(shù)字不同,Symbol值是唯一的,不可修改和可枚舉的。Symbol的主要用途包括:定義唯一屬性鍵、定義私有屬性、內(nèi)置Symbol和注冊全局Symbol。

此外,文章還介紹了兩個關(guān)于Symbol的提案:Symbols as WeakMap keysSymbol Predicates Proposal。這些提案旨在擴展Symbol的功能和用途,并為JavaScript開發(fā)人員提供更多的選項。

總之,SymbolJavaScript添加了一個新的基本數(shù)據(jù)類型,為開發(fā)人員提供了一種新的表示唯一標識符的方式,可以用于創(chuàng)建唯一屬性鍵、定義私有屬性、內(nèi)置Symbol和注冊全局Symbol等用途。

在實際項目中,如果遇到定義一個唯一的key的場景,就可以考慮使用 Symbol 來完成,可以避免沖突。

以上就是vscode工具函數(shù)Symbol使用深入解析的詳細內(nèi)容,更多關(guān)于vscode工具函數(shù)Symbol的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • npm腳本庫組織在項目中的地位詳解

    npm腳本庫組織在項目中的地位詳解

    這篇文章主要為大家介紹了npm腳本庫組織在項目中的地位詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-07-07
  • TypeScript 的條件類型使用示例詳解

    TypeScript 的條件類型使用示例詳解

    這篇文章主要為大家介紹了TypeScript 的條件類型使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-08-08
  • js的一些潛在規(guī)則使用分析

    js的一些潛在規(guī)則使用分析

    這篇文章主要為大家介紹了js的一些潛在規(guī)則使用分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-02-02
  • Thinkphp5微信小程序獲取用戶信息接口的實例詳解

    Thinkphp5微信小程序獲取用戶信息接口的實例詳解

    這篇文章主要介紹了Thinkphp5微信小程序獲取用戶信息接口的實例詳解的相關(guān)資料,希望通過本文能幫助到大家,需要的朋友可以參考下
    2017-09-09
  • 收集整理的四個方向的滾動

    收集整理的四個方向的滾動

    收集整理的四個方向的滾動...
    2006-06-06
  • 超越Node.js的JavaScript運行環(huán)境Bun.js功能特性詳解

    超越Node.js的JavaScript運行環(huán)境Bun.js功能特性詳解

    這篇文章主要為大家介紹了超越Node.js的JavaScript運行環(huán)境Bun.js功能特性詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-09-09
  • TypeScript實用技巧?Nominal?Typing名義類型詳解

    TypeScript實用技巧?Nominal?Typing名義類型詳解

    這篇文章主要為大家介紹了TypeScript實用技巧?Nominal?Typing名義類型詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-09-09
  • ECMAScript 6數(shù)值擴展實例詳解

    ECMAScript 6數(shù)值擴展實例詳解

    這篇文章主要為大家介紹了ECMAScript6數(shù)值擴展實例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-08-08
  • JavaScript中5個常用的對象

    JavaScript中5個常用的對象

    JavaScript是一門腳本語言,不同于Python的是,它是一門瀏覽器腳本語言,而Python則是服務(wù)器腳本語言,我們不光要會Python,還要會JavaScript,因為它對做網(wǎng)頁方面是有很大作用的。本篇內(nèi)容小編就來詳細解說JavaScript常用的對象,需要的朋友可以參考一下
    2021-10-10
  • JS開發(fā) 富文本編輯器TinyMCE詳解

    JS開發(fā) 富文本編輯器TinyMCE詳解

    這篇文章主要介紹了Java開發(fā) 富文本編輯器TinyMCE詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-07-07

最新評論