2021-03-09【阿里面試】有關symbol的一些知識(3)-內置方法

相關文章:【阿里面試】有關symbol的一些知識(1)-基礎知識
【阿里面試】有關symbol的一些知識(2)-實例
【阿里面試】有關symbol的一些知識(3)-內置方法

內置的 Symbol 值

除了定義自己使用的 Symbol 值以外勿侯,ES6 還提供了 11 個內置的 Symbol 值,指向語言內部使用的方法。

1. Symbol.hasInstance

對象的 Symbol.hasInstance 屬性蛔趴,指向一個內部方法。當其他對象使用 instanceof 運算符幅狮,判斷是否為該對象的實例時贡歧,會調用這個方法整胃。比如,foo instanceof Foo 在語言內部拷获,實際調用的是 Foo[Symbol.hasInstance](foo)

class MyClass {
  [Symbol.hasInstance](foo) {
    return foo instanceof Array;
  }
}

[1, 2, 3] instanceof new MyClass(); // true

MyClass 是一個類减细,new MyClass()會返回一個實例匆瓜。該實例的 Symbol.hasInstance 方法,會在進行 instanceof 運算時自動調用未蝌,判斷左側的運算子是否為 Array 的實例

class Even {
  static [Symbol.hasInstance](obj) {
    return Number(obj) % 2 === 0;
  }
}

// 等同于
const Even = {
  [Symbol.hasInstance](obj) {
    return Number(obj) % 2 === 0;
  },
};

1 instanceof Even; // false
2 instanceof Even; // true
12345 instanceof Even; // false

2. Symbol.isConcatSpreadable

對象的 Symbol.isConcatSpreadable 屬性等于一個布爾值驮吱,表示該對象用于 Array.prototype.concat()時,是否可以展開萧吠。

let arr1 = ["c", "d"];
["a", "b"].concat(arr1, "e"); // ['a', 'b', 'c', 'd', 'e']
arr1[Symbol.isConcatSpreadable]; // undefined

let arr2 = ["c", "d"];
arr2[Symbol.isConcatSpreadable] = false;
["a", "b"].concat(arr2, "e"); // ['a', 'b', ['c','d'], 'e']

上面代碼說明左冬,數(shù)組的默認行為是可以展開,Symbol.isConcatSpreadable 默認等于 undefined纸型。該屬性等于 true 時拇砰,也有展開的效果。

類似數(shù)組的對象正好相反狰腌,默認不展開除破。它的 Symbol.isConcatSpreadable 屬性設為 true,才可以展開琼腔。

let obj = { length: 2, 0: "c", 1: "d" };
["a", "b"].concat(obj, "e"); // ['a', 'b', obj, 'e']

obj[Symbol.isConcatSpreadable] = true;
["a", "b"].concat(obj, "e"); // ['a', 'b', 'c', 'd', 'e']

Symbol.isConcatSpreadable 屬性也可以定義在類里面瑰枫。

class A1 extends Array {
  constructor(args) {
    super(args);
    this[Symbol.isConcatSpreadable] = true;
  }
}
class A2 extends Array {
  constructor(args) {
    super(args);
  }
  get [Symbol.isConcatSpreadable]() {
    return false;
  }
}
let a1 = new A1();
a1[0] = 3;
a1[1] = 4;
let a2 = new A2();
a2[0] = 5;
a2[1] = 6;
[1, 2].concat(a1).concat(a2);
// [1, 2, 3, 4, [5, 6]]

注意,Symbol.isConcatSpreadable 的位置差異丹莲,A1 是定義在實例上光坝,A2 是定義在類本身,效果相同甥材。

3. Symbol.species

對象的 Symbol.species 屬性盯另,指向一個構造函數(shù)。創(chuàng)建衍生對象時擂达,會使用該屬性土铺。

class MyArray extends Array {}

const a = new MyArray(1, 2, 3);
const b = a.map((x) => x);
const c = a.filter((x) => x > 1);

b instanceof MyArray; // true
c instanceof MyArray; // true

Symbol.species 屬性就是為了解決這個問題而提供的〗鹤蹋現(xiàn)在,我們可以為 MyArray 設置 Symbol.species 屬性悲敷。

class MyArray extends Array {
  // 由于定義了Symbol.species屬性究恤,創(chuàng)建衍生對象時就會使用這個屬性返回的函數(shù),作為構造函數(shù)后德。
  static get [Symbol.species]() {
    return Array;
  }

  // 默認的Symbol.species屬性等同于下面的寫法
  // static get [Symbol.species]() {
  //   return this;
  // }
}
class MyArray extends Array {
  static get [Symbol.species]() {
    return Array;
  }
}

const a = new MyArray();
const b = a.map((x) => x);

b instanceof MyArray; // false
b instanceof Array; // true
class T1 extends Promise {}

class T2 extends Promise {
  static get [Symbol.species]() {
    return Promise;
  }
}

new T1((r) => r()).then((v) => v) instanceof T1; // true
new T2((r) => r()).then((v) => v) instanceof T2; // false

總之部宿,Symbol.species 的作用在于,實例對象在運行過程中瓢湃,需要再次調用自身的構造函數(shù)時理张,會調用該屬性指定的構造函數(shù)。

它主要的用途是绵患,有些類庫是在基類的基礎上修改的雾叭,那么子類使用繼承的方法時,作者可能希望返回基類的實例落蝙,而不是子類的實例织狐。

4. Symbol.match

對象的 Symbol.match 屬性,指向一個函數(shù)筏勒。當執(zhí)行 str.match(myObject)時移迫,如果該屬性存在,會調用它管行,返回該方法的返回值厨埋。

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

class MyMatcher {
  [Symbol.match](string) {
    return "hello world".indexOf(string);
  }
}

"e".match(new MyMatcher()); // 1

5. Symbol.replace

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

String.prototype.replace(searchValue, replaceValue);
// 等同于
searchValue[Symbol.replace](this, replaceValue);
const x = {};
x[Symbol.replace] = (...s) => console.log(s);

"Hello".replace(x, "World"); // ["Hello", "World"]

Symbol.replace 方法會收到兩個參數(shù)套菜,第一個參數(shù)是 replace 方法正在作用的對象亲善,上面例子是 Hello,第二個參數(shù)是替換后的值逗柴,上面例子是 World蛹头。

6. Symbol.search

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

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

class MySearch {
  constructor(value) {
    this.value = value;
  }
  [Symbol.search](string) {
    return string.indexOf(this.value);
  }
}
"foobar".search(new MySearch("foo")); // 0

7. Symbol.split

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

String.prototype.split(separator, limit);
// 等同于
separator[Symbol.split](this, limit);
// 使用Symbol.split方法骚烧,重新定義了字符串對象的split方法的行為浸赫,
class MySplitter {
  constructor(value) {
    this.value = value;
  }
  [Symbol.split](string) {
    let index = string.indexOf(this.value);
    if (index === -1) {
      return string;
    }
    return [string.substr(0, index), string.substr(index + this.value.length)];
  }
}

"foobar".split(new MySplitter("foo"));
// ['', 'bar']

"foobar".split(new MySplitter("bar"));
// ['foo', '']

"foobar".split(new MySplitter("baz"));
// 'foobar'

8. Symbol.iterator

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

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

[...myIterable]; // [1, 2, 3]

對象進行 for...of 循環(huán)時既峡,會調用 Symbol.iterator 方法,返回該對象的默認遍歷器

class Collection {
  *[Symbol.iterator]() {
    let i = 0;
    while (this[i] !== undefined) {
      yield this[i];
      ++i;
    }
  }
}

let myCollection = new Collection();
myCollection[0] = 1;
myCollection[1] = 2;

for (let value of myCollection) {
  console.log(value);
}
// 1
// 2

9. Symbol.toPrimitive

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

Symbol.toPrimitive 被調用時,會接受一個字符串參數(shù)稻扬,表示當前運算的模式卦方,一共有三種模式。

  • Number:該場合需要轉成數(shù)值
  • String:該場合需要轉成字符串
  • Default:該場合可以轉成數(shù)值泰佳,也可以轉成字符串
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; // 246
3 + obj; // '3default'
obj == "default"; // true
String(obj); // 'str'

10. Symbol.toStringTag

對象的 Symbol.toStringTag 屬性愿汰,指向一個方法。在該對象上面調用 Object.prototype.toString 方法時乐纸,如果這個屬性存在,它的返回值會出現(xiàn)在 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]"

ES6 新增內置對象的 Symbol.toStringTag 屬性值如下宁昭。

  • JSON[Symbol.toStringTag]:'JSON'
  • Math[Symbol.toStringTag]:'Math'
  • Module 對象M[Symbol.toStringTag]:'Module'
  • ArrayBuffer.prototype[Symbol.toStringTag]:'ArrayBuffer'
  • DataView.prototype[Symbol.toStringTag]:'DataView'
  • Map.prototype[Symbol.toStringTag]:'Map'
  • Promise.prototype[Symbol.toStringTag]:'Promise'
  • Set.prototype[Symbol.toStringTag]:'Set'
  • %TypedArray%.prototype[Symbol.toStringTag]:'Uint8Array'等
  • WeakMap.prototype[Symbol.toStringTag]:'WeakMap'
  • WeakSet.prototype[Symbol.toStringTag]:'WeakSet'
  • %MapIteratorPrototype%[Symbol.toStringTag]:'Map Iterator'
  • %SetIteratorPrototype%[Symbol.toStringTag]:'Set Iterator'
  • %StringIteratorPrototype%[Symbol.toStringTag]:'String Iterator'
  • Symbol.prototype[Symbol.toStringTag]:'Symbol'
  • Generator.prototype[Symbol.toStringTag]:'Generator'
  • GeneratorFunction.prototype[Symbol.toStringTag]:'GeneratorFunction'

11. Symbol.unscopables

對象的 Symbol.unscopables 屬性,指向一個對象酗宋。該對象指定了使用 with 關鍵字時积仗,哪些屬性會被 with 環(huán)境排除。

Array.prototype[Symbol.unscopables];
// {
//   copyWithin: true,
//   entries: true,
//   fill: true,
//   find: true,
//   findIndex: true,
//   includes: true,
//   keys: true
// }

Object.keys(Array.prototype[Symbol.unscopables]);
// ['copyWithin', 'entries', 'fill', 'find', 'findIndex', 'includes', 'keys']
// 沒有 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.unscopables 屬性蜕猫,使得 with 語法塊不會在當前作用域尋找 foo 屬性寂曹,即 foo 將指向外層作用域的變量。

MDN with關鍵字

原文:# ECMAScript 6 入門

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末回右,一起剝皮案震驚了整個濱河市隆圆,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌翔烁,老刑警劉巖渺氧,帶你破解...
    沈念sama閱讀 211,376評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異蹬屹,居然都是意外死亡侣背,警方通過查閱死者的電腦和手機白华,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,126評論 2 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來贩耐,“玉大人弧腥,你說我怎么就攤上這事°狙睿” “怎么了鸟赫?”我有些...
    開封第一講書人閱讀 156,966評論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長消别。 經常有香客問我抛蚤,道長,這世上最難降的妖魔是什么寻狂? 我笑而不...
    開封第一講書人閱讀 56,432評論 1 283
  • 正文 為了忘掉前任岁经,我火速辦了婚禮,結果婚禮上蛇券,老公的妹妹穿的比我還像新娘缀壤。我一直安慰自己,他們只是感情好纠亚,可當我...
    茶點故事閱讀 65,519評論 6 385
  • 文/花漫 我一把揭開白布塘慕。 她就那樣靜靜地躺著,像睡著了一般蒂胞。 火紅的嫁衣襯著肌膚如雪图呢。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,792評論 1 290
  • 那天骗随,我揣著相機與錄音蛤织,去河邊找鬼。 笑死鸿染,一個胖子當著我的面吹牛指蚜,可吹牛的內容都是我干的。 我是一名探鬼主播涨椒,決...
    沈念sama閱讀 38,933評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼摊鸡,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了丢烘?” 一聲冷哼從身側響起柱宦,我...
    開封第一講書人閱讀 37,701評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎播瞳,沒想到半個月后掸刊,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 44,143評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡赢乓,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,488評論 2 327
  • 正文 我和宋清朗相戀三年忧侧,在試婚紗的時候發(fā)現(xiàn)自己被綠了石窑。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,626評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡蚓炬,死狀恐怖松逊,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 34,292評論 4 329
  • 正文 年R本政府宣布茂缚,位于F島的核電站,受9級特大地震影響烁兰,放射性物質發(fā)生泄漏。R本人自食惡果不足惜徊都,卻給世界環(huán)境...
    茶點故事閱讀 39,896評論 3 313
  • 文/蒙蒙 一沪斟、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧暇矫,春花似錦主之、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,742評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至房轿,卻和暖如春史翘,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背冀续。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留必峰,地道東北人洪唐。 一個月前我還...
    沈念sama閱讀 46,324評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像吼蚁,于是被迫代替她去往敵國和親凭需。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,494評論 2 348

推薦閱讀更多精彩內容