阿里云主机折上折
  • 微信号
您当前的位置:网站首页 > 内置Symbol值

内置Symbol值

作者:陈川 阅读数:5090人阅读 分类: JavaScript

ECMAScript 6 引入了Symbol类型作为新的原始数据类型,同时还内置了一系列标准Symbol值,用于扩展对象的行为。这些内置Symbol值通过Symbol函数的属性暴露,例如Symbol.iteratorSymbol.toStringTag,它们定义了对象的默认迭代行为或字符串描述等特性。

Symbol.iterator

Symbol.iterator定义了对象的默认迭代器。如果一个对象实现了Symbol.iterator方法,那么它就是可迭代的,可以被for...of循环遍历。

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

for (const value of myIterable) {
  console.log(value); // 依次输出 1, 2, 3
}

数组、字符串、Map、Set等内置类型都默认实现了Symbol.iterator方法:

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用于定制对象在调用Object.prototype.toString()时返回的字符串标签。默认情况下,普通对象调用toString()会返回[object Object],但通过定义Symbol.toStringTag可以改变这一行为。

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

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

内置类型如MapSet也使用了这一特性:

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

Symbol.species

Symbol.species用于指定派生对象的构造函数。当需要创建派生对象(如数组的mapfilter方法返回的新数组)时,会使用Symbol.species指定的构造函数。

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用于自定义instanceof操作符的行为。默认情况下,instanceof会检查对象的原型链,但通过定义Symbol.hasInstance可以覆盖这一逻辑。

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用于控制数组或类数组对象在调用concat方法时是否展开。默认情况下,数组会展开,而类数组对象不会。

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

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

对于类数组对象,可以通过设置Symbol.isConcatSpreadabletrue来使其展开:

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用于定义对象转换为原始值时的行为。当对象需要转换为字符串、数字或默认原始值时,会调用该方法。

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用于定义对象在被String.prototype.match调用时的行为。如果对象实现了Symbol.match方法,那么它可以被用作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用于定义对象在被String.prototype.replace调用时的行为。例如,可以自定义替换逻辑:

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

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

Symbol.search

Symbol.search用于定义对象在被String.prototype.search调用时的行为。可以自定义搜索逻辑:

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

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

Symbol.split

Symbol.split用于定义对象在被String.prototype.split调用时的行为。可以自定义分割逻辑:

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用于指定对象的哪些属性不应该被with语句绑定。这是一个历史遗留特性,现代代码中很少使用with语句。

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

前端川

前端川,陈川的代码茶馆🍵,专治各种不服的Bug退散符💻,日常贩卖秃头警告级的开发心得🛠️,附赠一行代码笑十年的摸鱼宝典🐟,偶尔掉落咖啡杯里泡开的像素级浪漫☕。‌