ES6——Symbol

ES6——Symbol

Symbol

  1. 出现的原因: 对象的属性容易重复,导致出现问题,Symbol的出现,解决了这个问题。
  2. 不能使用new 关键词进行声明
  3. Symbol属于原始类型,类似字符串的数据类型
  4. Symbol 接受一个参数,该参数属于对Symbol的描述,该参数暂时没有太多限制,参数只是描述,就算参数一致,但Symbol还是不一样的。
  5. Symbol 不能 与其他值进行 运算(字符串拼接,或者是字符串模板也不可以)
  6. Symbol值可以字符串以及布尔型,但不能转数值(原因是第5条)
  7. Symbol的描述参数可以使用description进行展示出来。即 Symbol(‘foo’).description === ‘foo’
  8. Symbol 作为对象属性名时,只能使用[],不能使用点。属于公有属性,非私有属性
  9. Symbol在对象中声明的属性,只能使用Object.getOwnPropertySymbols(),ES6提供的一个新的Reflect.ownKeys()也可以获取
  10. Symbol.for() 也是声明Symbol,不过 通过它声明,可以判断某些描述是否已经存在。 存在,返回对应的Symbol,否则就是创建 该方式声明的,可以在全局供搜索到。
  11. Symbol.keyFor() 能获取到 Symbol.for() 声明的Symbol的描述值
const s2 = Symbol.for('foo')
const foo = Symbol.keyFor(s2)
console.log(foo) // foo
  1. Symbol 内置的属性方法
    1. Symbol.hasInstance 这个方法,在W3C上面说明的是, 指向一个内部方法,当其他对象使用 instanceof运算符,判断是否为该对象的实例时,会调用这个方法。 而后所给的例子,主要是用instanceof 去进行操作是否在对象中。 所以暂时得出的结论,这个方法是可以重写对象的instanceof的方法
    2. Symbol.isConcatSpreadable 属性等于一个布尔值,表示该对象用于 Array.prototype.concat()时,是否可以展开。
    3. Symbol.species 对象的Symbol.species 属性,指向一个构造函数。创建衍生对象时(例子:声明一个类,该类继承Array类,然后创建实例,该实例使用map方法生成一个新的数组实例,问:新的数组实例的原型指向谁?该新的数组实例属于衍生对象吗?),会使用该属性。不过,使用时,需要在类里面使用 get 放在前面(例子: get Symbol.species { return this }) 总之, Symbol.species 的作用在于,实例对象在运行过程中,需要再次调用自身的构造函数时,会调用该属性指定的构造函数。它主要的用途是,有些类库是在基类的基础上修改的,那么子类使用继承的方法时,作者可能希望返回基类的实例,而不是子类的实例。
    4. Symbol.match 对象的 Symbol.match属性,指向一个函数。当执行str.match(myObject) 时,如果该属性存在,会调用它,返回该方法的返回值。(字符串的match方法)
    5. Symbol.replace 对象的Symbol.replace属性,指向一个方法,当该对象被String.prototype.replace方法调用时,会返回该方法的返回值。(字符串的replace方法)
    6. Symbol.search 对象的 Symbol.search 属性,指向一个方法,当该对象被 String.prototype.search 方法调用时,会返回该方法的返回值。(字符串的search)
    7. Symbol.split 对象的Symbol.split 属性,指向一个方法,当该对象被String.prototype.split方法调用时,会返回该方法的返回值。(字符串的split方法)
    8. Symbol.iterator 对象的Symbol.iterator属性,指向该对象的默认遍历器方法。(主要指向iterator,配合for…of 的使用)
    9. Symbol.toPrimitive 对象的Symbol.toPrimitive 属性,指向一个方法。该对象被转为原始类型的值时,会调用这个方法,返回该对象对应的原始类型值。Symbol.toPrimitive 被调用时,会接受一个字符串参数,表示当前运算的模式,一共有三种模式。Number, String, Default(可以转字符串,或者转数字)
    10. Symbol.toStringTag 对象的Symbol.toStringTag属性,指向一个方法。在该对象上面调用 Object.prototype.toString方法时,如果这个属性存在,它的返回值会出现在 toString 方法返回的字符串之中,表示对象的类型。也就是说,这个属性可以用来定制 [object Object] 或 [object Array] 中 object 后面的那个字符串。
      • 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 环境排除。 例子: 代码通过指定Symbol.unscopables属性,使得 with 语法块不会在当前作用域寻找 foo 属性,即 foo 将指向外层作用域的变量。
// 12-1 Symbol.hasInstance 例子
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
// 12-2 Symbol.isConcatSpreadable例子
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']

let obj = {length: 2, 0: 'c', 1: 'd'}
obj[Symbol.isConcatSpreadable] = true
['a','b'].concat(obj, '1') // ['a', 'b', 'c', 'd', '1']
// 12-3 Symbol.species 例子
class MyClass extends Array {
}

const a = new MyClass([1,2,3])
const b = a.map(item => item*2)
const c = b.filter(item => item === 4)

b instanceof MyClass// true
c instanceof MyClass// true

class MyArray extends Array {
static get[Symbol.species]() {
return Array
}
const d = new MyArray([1,2,3])
const e = d.map(item => item*2)
e instanceof MyArray // false
e instanceof Array// true
// 12-4 Symbol.match 例子 12-5,12-6,12-7 基本都是这种用法
String.prototype.match(regexp)
// 等同于
regexp[Symbol.match](this)

class MyMatcher {
  [Symbol.match](string) {
    return 'hello world'.indexOf(string);
  }
}
'e'.match(new MyMatcher()) // 1
// 12-8 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);
}
// 12-9 Symbol-toPrimitive 例子:
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'
// 12-10  Symbol.toStringTag 例子
// 例一
({[Symbol.toStringTag]: 'Foo'}.toString())
// "[object Foo]"
// 例二
class Collection {
  get [Symbol.toStringTag]() {
    return 'xxx';
  }
}
let x = new Collection();
Object.prototype.toString.call(x) // "[object xxx]"

// 12-11 Symbol.unscopables 例子
// 没有 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
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值