深入理解ES6--Set、Map及Symbol

Set集合和Map集合

Set集合是一种无重复元素的列表,通常用来检测给定的值在某个集合中是否存在;Map集合内含多组键值对,通常用来缓存频繁取用的数据。

ES5中的问题

var map = Object.create(null)
map[5] = 'foo'
console.log(map[5], map['5']) // 'foo' 'foo'

let key1 = {}
let key2 = {}
map[key1] = 'bar'
console.log(map[key2]) // 'bar'

由于对象属性名必须是字符串,所以5会转换为字符串”5”;而key1和key2会转换为["object Object"]对于,Set集合和Map集合是严格区分的,通过Object.is()判断实现

Set去重

let ary = [1, 2, 3, 2, 3]
let distAry = [...new Set(ary)] // [1, 2, 3]

forEach函数

myAry.forEach(callback(currentValue, index, array){}, this)
mySet.forEach(callback(value1, value2, set){}, this)
myMap.forEach(callback(value, key, Map){}, thisArg])

Symbol

Symbol 是继字符串、数值、布尔值、null、undefined后的第6中原始类型,但和其原始类型不同的是,Symbol没有字面量形式。

Symbol共享体系

有时希望在不同代码中共享一个Symbol,ES6中提供了一个可随时访问的全局Symbol注册表,可通过Symbol.for()创建共享的Symbol。

let name = Symbol.for('name')
let p = {
    [name]: 'ligang'
}
let otherName = Symbol.for('name')
console.log(name === otherName) // true
console.log(p[otherName]) // 'ligang'

属性检索

let name = Symbol.for('name')
let p = {
    [name]: 'ligang',
    age: 28
}
Object.defineProperty(p, 'age', {enumerable: false})

console.log(Object.keys(p)) // []
console.log(Object.getOwnPropertyNames(p)) // ["age"]
console.log(Object.getOwnPropertySymbols(p)) // [Symbol(name)]
  • Object.keys():返回一个由一个给定对象的自身可枚举属性组成的数组;

    与 for-in主要区别是,or-in 循环还会枚举其原型链上的属性

  • Object.getOwnPropertyNames():返回一个由指定对象的所有自身属性的属性名(包括不可枚举属性但不包括Symbol值作为名称的属性)组成的数组;

  • Object.getOwnPropertySymbols():返回一个给定对象自身的所有 Symbol 属性的数组

通过well-known Symbol暴露内部操作

ES6通过在原型链上定义与Symbol相关的属性来暴露更多的语言内部逻辑。

  • Symbol.hasInstance用于判断某对象是否为某构造器的实例;可以用它自定义instanceof操作符在某个类上的行为 ;
  • Symbol.isConcatSpreadable:用于配置某对象作为Array.prototype.concat()方法的参数时是否展开其数组元素;
  • Symbol.match:指定了匹配的是正则表达式而不是字符串;String.prototype.match()方法会调用此函数;
  • Symbol.iterator:为每一个对象定义了默认的迭代器;该迭代器可以被 for...of 循环使用;
  • Symbol.replace :指定了当一个字符串替换所匹配字符串时所调用的方法。String.prototype.replace()方法会调用此方法;
  • Symbol.search:定了一个搜索方法,这个方法接受用户输入的正则表达式,返回该正则表达式在字符串中匹配到的下标,这个方法由以下的方法来调用 String.prototype.search() ;
  • Symbol.species:是个函数值属性,其被构造函数用以创建派生对象;
  • Symbol.split:指向 一个正则表达式的索引处分割字符串的方法。 这个方法通过 String.prototype.split() 调用;
  • Symbol.toPrimitive:将被调用的指定函数值的属性转换为相对应的原始值;
  • Symbol.toStringTag:一个内置 symbol,它通常作为对象的属性键使用,对应的属性值应该为字符串类型,这个字符串用来表示该对象的自定义类型标签,通常只有内置的 Object.prototype.toString() 方法会去读取这个标签并把它包含在自己的返回值里。

Symbol .hasInstance

let Person = function(name) {this.name = name}
let p = new Person('ligang')
console.log(p instanceof Person) // true
console.log(Person[Symbol.hasInstance](p)) // true

// 修改Symbol .hasInstance行为
Object.defineProperty(Person, Symbol.hasInstance, {
    value: function(v) {
        return false
    }
})
let p2 = new Person('ligang')
console.log(p2 instanceof Person) // false
console.log(Person[Symbol.hasInstance](p2)) // false

Symbol.toPrimitive

在一些操作时,我们会经常讲对象转换为相应的原始值(如,+,==)。Symbol.toPrimitive方法被定义在每一个标准类型的原型上,并且规定了当对象转换为原始值时应当执行的操作。Symbol.toPrimitive会接收类型提示参数(“number”、“string”和“default”之一)。

对于大多数标准对象,数字模式优先级如下:

  1. 调用valueOf()方法,如果结果为原始值,则返回;
  2. 否则,调用toString()方法,如果结果为原始值,则返回;
  3. 如果再无可选值,抛出错误。

对于大多数标准对象,字符串模式优先级如下:

  1. 调用toString()方法,如果结果为原始值,则返回;
  2. 否则,调用valueOf()方法,如果结果为原始值,则返回;
  3. 如果再无可选值,抛出错误。
// 没有 Symbol.toPrimitive 属性的对象
var obj1 = {};
console.log(+obj1);     // NaN
console.log(`${obj1}`); // "[object Object]"
console.log(obj1 + ""); // "[object Object]"

// 拥有 Symbol.toPrimitive 属性的对象
var obj2 = {
  [Symbol.toPrimitive](hint) {
    if (hint == "number") {
      return 10;
    }
    if (hint == "string") {
      return "hello";
    }
    return true;
  }
};
console.log(+obj2);     // 10      -- hint is "number"
console.log(`${obj2}`); // "hello" -- hint is "string"
console.log(obj2 + ""); // "true"  -- hint is "default"

你可能感兴趣的:(ES6,ES6)