阿里云主机折上折
  • 微信号
Current Site:Index > Built-in Symbol values

Built-in Symbol values

Author:Chuan Chen 阅读数:5088人阅读 分类: JavaScript

ECMAScript 6 introduced the Symbol type as a new primitive data type, along with a series of standard Symbol values to extend object behavior. These built-in Symbol values are exposed as properties of the Symbol function, such as Symbol.iterator and Symbol.toStringTag, which define default iteration behavior or string descriptions for objects, among other features.

Symbol.iterator

Symbol.iterator defines the default iterator for an object. If an object implements the Symbol.iterator method, it is iterable and can be traversed using a for...of loop.

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

for (const value of myIterable) {
  console.log(value); // Outputs 1, 2, 3 in sequence
}

Built-in types like arrays, strings, Map, and Set already implement the Symbol.iterator method by default:

const arr = [1, 2, 3];
const iterator = arr[Symbol.iterator]();

console.log(iterator.next()); // { value: 1, done: false }
console.log(iterator.next()); // { value: 2, done: false }
console.log(iterator.next()); // { value: 3, done: false }
console.log(iterator.next()); // { value: undefined, done: true }

Symbol.toStringTag

Symbol.toStringTag is used to customize the string tag returned when Object.prototype.toString() is called on an object. By default, a plain object returns [object Object], but defining Symbol.toStringTag can change this behavior.

class MyClass {
  get [Symbol.toStringTag]() {
    return 'MyClass';
  }
}

const obj = new MyClass();
console.log(Object.prototype.toString.call(obj)); // [object MyClass]

Built-in types like Map and Set also use this feature:

console.log(Object.prototype.toString.call(new Map())); // [object Map]
console.log(Object.prototype.toString.call(new Set())); // [object Set]

Symbol.species

Symbol.species specifies the constructor for derived objects. When creating derived objects (e.g., new arrays returned by map or filter methods), the constructor specified by Symbol.species is used.

class MyArray extends Array {
  static get [Symbol.species]() {
    return Array;
  }
}

const myArray = new MyArray(1, 2, 3);
const mappedArray = myArray.map(x => x * 2);

console.log(mappedArray instanceof MyArray); // false
console.log(mappedArray instanceof Array); // true

Symbol.hasInstance

Symbol.hasInstance customizes the behavior of the instanceof operator. By default, instanceof checks the object's prototype chain, but defining Symbol.hasInstance can override this logic.

class MyClass {
  static [Symbol.hasInstance](instance) {
    return typeof instance === 'number';
  }
}

console.log(1 instanceof MyClass); // true
console.log('1' instanceof MyClass); // false

Symbol.isConcatSpreadable

Symbol.isConcatSpreadable controls whether an array or array-like object is spread when the concat method is called. By default, arrays are spread, while array-like objects are not.

const arr1 = [1, 2];
const arr2 = [3, 4];
arr2[Symbol.isConcatSpreadable] = false;

console.log(arr1.concat(arr2)); // [1, 2, [3, 4]]

For array-like objects, setting Symbol.isConcatSpreadable to true allows them to be spread:

const arrayLike = {
  0: 'a',
  1: 'b',
  length: 2,
  [Symbol.isConcatSpreadable]: true
};

console.log(['x', 'y'].concat(arrayLike)); // ['x', 'y', 'a', 'b']

Symbol.toPrimitive

Symbol.toPrimitive defines how an object is converted to a primitive value. When an object needs to be converted to a string, number, or default primitive value, this method is called.

const obj = {
  [Symbol.toPrimitive](hint) {
    if (hint === 'number') {
      return 42;
    }
    if (hint === 'string') {
      return 'forty-two';
    }
    return 'default';
  }
};

console.log(+obj); // 42
console.log(`${obj}`); // "forty-two"
console.log(obj + ''); // "default"

Symbol.match

Symbol.match defines how an object behaves when passed to String.prototype.match. If an object implements Symbol.match, it can be used as an argument for match.

class MyMatcher {
  [Symbol.match](string) {
    return string.indexOf('hello') !== -1;
  }
}

console.log('hello world'.match(new MyMatcher())); // true
console.log('hi world'.match(new MyMatcher())); // false

Symbol.replace

Symbol.replace defines how an object behaves when passed to String.prototype.replace. For example, custom replacement logic can be implemented:

class MyReplacer {
  [Symbol.replace](string, replacement) {
    return string.split(' ').join(replacement);
  }
}

console.log('hello world'.replace(new MyReplacer(), '-')); // "hello-world"

Symbol.search

Symbol.search defines how an object behaves when passed to String.prototype.search. Custom search logic can be implemented:

class MySearcher {
  [Symbol.search](string) {
    return string.indexOf('world');
  }
}

console.log('hello world'.search(new MySearcher())); // 6

Symbol.split

Symbol.split defines how an object behaves when passed to String.prototype.split. Custom splitting logic can be implemented:

class MySplitter {
  [Symbol.split](string) {
    return string.split(' ').map(word => word.toUpperCase());
  }
}

console.log('hello world'.split(new MySplitter())); // ["HELLO", "WORLD"]

Symbol.unscopables

Symbol.unscopables specifies which properties of an object should not be bound by a with statement. This is a legacy feature, as modern code rarely uses with statements.

const obj = {
  a: 1,
  b: 2,
  [Symbol.unscopables]: {
    a: true
  }
};

with (obj) {
  console.log(b); // 2
  console.log(a); // ReferenceError: a is not defined
}

本站部分内容来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn

Front End Chuan

Front End Chuan, Chen Chuan's Code Teahouse 🍵, specializing in exorcising all kinds of stubborn bugs 💻. Daily serving baldness-warning-level development insights 🛠️, with a bonus of one-liners that'll make you laugh for ten years 🐟. Occasionally drops pixel-perfect romance brewed in a coffee cup ☕.