中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

JavaScript中Symbol是什么

發布時間:2022-03-22 11:36:28 來源:億速云 閱讀:374 作者:小新 欄目:web開發

這篇文章主要介紹了JavaScript中Symbol是什么,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。

什么是 Symbol?為什么會有這么個東西?

Symbol(符號)是 ES6 新增的數據類型。Symbol 是原始值(基礎數據類型),且 Symbol 實例是唯一、不可變的。它的產生是因為要用來唯一的標記,進而用作非字符串形式的對象屬性,是確保對象屬性使用唯一標識符,不會發生屬性沖突的危險。【相關推薦:javascript學習教程】

用法

1. 基本用法

符號需要使用 Symbol()函數初始化。因為符號本身是原始類型,所以 typeof 操作符對符號返回 symbol。

let sym = Symbol();
console.log(typeof sym); // symbol

Symbol()函數可以接收一個字符串參數用來描述,后,后續可以通過這個字符串來調試代碼。但值得注意的是,多個 Symbol()函數即使接受的參數是一樣的,他們的值也是不相等的。

let genericSymbol = Symbol();
let otherGenericSymbol = Symbol();
let fooSymbol = Symbol("foo");
let otherFooSymbol = Symbol("foo");

console.log(genericSymbol == otherGenericSymbol); // false
console.log(fooSymbol == otherFooSymbol); // false

2. 使用全局符號注冊表

如果在代碼中有多個地方需要使用同一個 Symbol 實例的時候,可以傳入一個字符串,然后使用 Symbol.for()方法來創建一個可以復用的 Symbol,類似于單例模式,在第一次使用 Symbol.for()的時候,它會根據傳入的參數會全局的去尋找是否使用 Symbol.for()創建過同樣的實例,如果有,則復用,如果沒有,則新建

let fooGlobalSymbol = Symbol.for("foo"); // 創建新符號
let otherFooGlobalSymbol = Symbol.for("foo"); // 重用已有符號
console.log(fooGlobalSymbol === otherFooGlobalSymbol); // true

Symbol.for()創建的實例和 Symbol()創建的實例區別: Symbol()創建的實例永遠都是唯一的,不會因為你傳入的參數相同而跟其他的實例相等,但是 Symbol.for()創建的實例如果參數相同的話他們是會相等的,因為他們會公用同一個 Symbol 實例

let fooSymbol = Symbol("foo");
let otherFooSymbol = Symbol("foo");
console.log(fooSymbol == otherFooSymbol); // false

let fooGlobalSymbol = Symbol.for("foo"); // 創建新符號
let otherFooGlobalSymbol = Symbol.for("foo"); // 重用已有符號
console.log(fooGlobalSymbol === otherFooGlobalSymbol); // true

3. 使用符號作為屬性

對象中的屬性一般都是字符串的形式,但其實也是可以使用 Symbol 實例來作為屬性的,這樣的好處就是你新增的屬性不會覆蓋掉以前的任何屬性

let s1 = Symbol("foo"),
  s2 = Symbol("bar"),
  s3 = Symbol("baz"),
  s4 = Symbol("qux");
let o = {
  [s1]: "foo val",
};
// 這樣也可以:o[s1] = 'foo val';
console.log(o);
// {Symbol(foo): foo val}
Object.defineProperty(o, s2, { value: "bar val" });
console.log(o);
// {Symbol(foo): foo val, Symbol(bar): bar val}
Object.defineProperties(o, {
  [s3]: { value: "baz val" },
  [s4]: { value: "qux val" },
});
console.log(o);
// {Symbol(foo): foo val, Symbol(bar): bar val,
// Symbol(baz): baz val, Symbol(qux): qux val}

注意: 創建 Symbol 實例作為對象屬性的時候,如果改 symbol 一開始沒有聲明一個變量進行接收的話,后續就必須遍歷對象的所有符號屬性才能找到相應的屬性鍵:

let o = {
  [Symbol("foo")]: "foo val",
  [Symbol("bar")]: "bar val",
};
console.log(o);
// {Symbol(foo): "foo val", Symbol(bar): "bar val"}
let barSymbol = Object.getOwnPropertySymbols(o).find(symbol => symbol.toString().match(/bar/));
console.log(barSymbol);
// Symbol(bar)

4. 常用內置符號

ES6 也引入了一批常用內置符號(well-known symbol),用于暴露語言內部行為,開發者可以直接訪問、重寫或模擬這些行為。如果對這些默認的屬性進行了修改的話,是可以改變一些操作最后執行的結果的。比如 for-of 循環會在相關對象上使用 Symbol.iterator 屬性,那么就可以通過在自定義對象上重新定義 Symbol.iterator 的值,來改變 for-of 在迭代該對象時的行為。

5. Symbol.asyncIterator

其實就是一個返回 Promise 的 Generator,一般配合 for await of 使用

6. Symbol.hasInstance

根據 ECMAScript 規范,這個符號作為一個屬性表示“一個方法,該方法返回對象默認的 AsyncIterator。 由 for-await-of 語句使用”。換句話說,這個符號表示實現異步迭代器 API 的函數。

這個屬性定義在 Function 的原型上。都知道 instanceof 操作符可以用來確定一個對象實例是否屬于某個構造函數。其原理就是 instanceof 操作符會使用 Symbol.hasInstance 函數來確定關系

function Foo() {}
let f = new Foo();
console.log(f instanceof Foo); // true
class Bar {}
let b = new Bar();
console.log(b instanceof Bar); // true

如果你重新定義一個函數的 Symbol.hasInstance 屬性,你就可以讓 instanceof 方法返回一些意料之外的東西

class Bar {}
class Baz extends Bar {
  static [Symbol.hasInstance]() {
    return false;
  }
}
let b = new Baz();
console.log(Bar[Symbol.hasInstance](b)); // true
console.log(b instanceof Bar); // true
console.log(Baz[Symbol.hasInstance](b)); // false
console.log(b instanceof Baz); // false

Symbol.isConcatSpreadabl

這個屬性定義在 Array 的原型上

根據 ECMAScript 規范,這個符號作為一個屬性表示“一個布爾值,如果是 true,則意味著對象應該用 Array.prototype.concat()打平其數組元素”。ES6 中的 Array.prototype.concat()方法會 根據接收到的對象類型選擇如何將一個類數組(偽數組)對象拼接成數組實例。所以修改 Symbol.isConcatSpreadable 的值可以修改這個行為。

Symbol.isConcatSpreadable 對應的效果

false: 將一整個對象添加進數組true: 將一整個對打平添加進數組

let initial = ["foo"];
let array = ["bar"];
console.log(array[Symbol.isConcatSpreadable]); // undefined
console.log(initial.concat(array)); // ['foo', 'bar']
array[Symbol.isConcatSpreadable] = false;
console.log(initial.concat(array)); // ['foo', Array(1)]
let arrayLikeObject = { length: 1, 0: "baz" };
console.log(arrayLikeObject[Symbol.isConcatSpreadable]); // undefined
console.log(initial.concat(arrayLikeObject)); // ['foo', {...}]

arrayLikeObject[Symbol.isConcatSpreadable] = true;
console.log(initial.concat(arrayLikeObject)); // ['foo', 'baz']
let otherObject = new Set().add("qux");
console.log(otherObject[Symbol.isConcatSpreadable]); // undefined
console.log(initial.concat(otherObject)); // ['foo', Set(1)]
otherObject[Symbol.isConcatSpreadable] = true;
console.log(initial.concat(otherObject)); // ['foo']

8. Symbol.iterator

根據 ECMAScript 規范,這個符號作為一個屬性表示“一個方法,該方法返回對象默認的迭代器。由 for-of 語句使用”

該屬性會返回一個 Generator 函數,for of 就會依次的去調用 next()方法,這就是為什么 for of 可以使用在某些對象身上。

class Emitter {
  constructor(max) {
    this.max = max;
    this.idx = 0;
  }
  *[Symbol.iterator]() {
    while (this.idx < this.max) {
      yield this.idx++;
    }
  }
}
function count() {
  let emitter = new Emitter(5);
  for (const x of emitter) {
    console.log(x);
  }
}
count();
// 0
// 1
// 2
// 3
// 4

9. Symbol.match

根據 ECMAScript 規范,這個符號作為一個屬性表示“一個正則表達式方法,該方法用正則表達式去匹配字符串。由 String.prototype.match()方法使用”。

String.prototype.match()方法會使用以 Symbol.match 為鍵的函數來對正則表達式求值。所以更改一個正則表達式的 Symbol.match 屬性,可以讓 String.prototype.match()得到你想要的值

console.log(RegExp.prototype[Symbol.match]);
// ? [Symbol.match]() { [native code] }
console.log("foobar".match(/bar/));
// ["bar", index: 3, input: "foobar", groups: undefined]

class FooMatcher {
  static [Symbol.match](target) {
    return target.includes("foo");
  }
}
console.log("foobar".match(FooMatcher)); // true
console.log("barbaz".match(FooMatcher)); // false
class StringMatcher {
  constructor(str) {
    this.str = str;
  }
  [Symbol.match](target) {
    return target.includes(this.str);
  }
}
console.log("foobar".match(new StringMatcher("foo"))); // true
console.log("barbaz".match(new StringMatcher("qux"))); // false

11. Symbol.search

這個符號作為一個屬性表示“一個正則表達式方法,該方法返回字符串中 匹配正則表達式的索引。由 String.prototype.search()方法使用”

12. Symbol.species

這個符號作為一個屬性表示“一個函數值,該函數作為創建派生對象的構 造函數”。

13. Symbol.split

這個符號作為一個屬性表示“一個正則表達式方法,該方法在匹配正則表 達式的索引位置拆分字符串。由 String.prototype.split()方法使用”。

14. Symbol.toPrimitive

這個符號作為一個屬性表示“一個方法,該方法將對象轉換為相應的原始 值。由 ToPrimitive 抽象操作使用”

15. Symbol.toStringTag

這個符號作為一個屬性表示“一個字符串,該字符串用于創建對象的默認 字符串描述。由內置方法 Object.prototype.toString()使用”

16. Symbol.unscopables

這個符號作為一個屬性表示“一個對象,該對象所有的以及繼承的屬性, 都會從關聯對象的 with 環境綁定中排除

感謝你能夠認真閱讀完這篇文章,希望小編分享的“JavaScript中Symbol是什么”這篇文章對大家有幫助,同時也希望大家多多支持億速云,關注億速云行業資訊頻道,更多相關知識等著你來學習!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

阿勒泰市| 绥中县| 扎囊县| 太湖县| 襄垣县| 安乡县| 天水市| 即墨市| 辉县市| 安福县| 绿春县| 云阳县| 栾川县| 通榆县| 金山区| 连山| 南溪县| 宁乡县| 会昌县| 台东市| 万源市| 武安市| 远安县| 柞水县| 乐安县| 平舆县| 正安县| 宽甸| 姜堰市| 汉源县| 阳谷县| 长沙市| 西乡县| 柯坪县| 滦平县| 西盟| 朝阳市| 榆树市| 肇东市| 南昌市| 虎林市|