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”之一)。
对于大多数标准对象,数字模式优先级如下:
- 调用valueOf()方法,如果结果为原始值,则返回;
- 否则,调用toString()方法,如果结果为原始值,则返回;
- 如果再无可选值,抛出错误。
对于大多数标准对象,字符串模式优先级如下:
- 调用toString()方法,如果结果为原始值,则返回;
- 否则,调用valueOf()方法,如果结果为原始值,则返回;
- 如果再无可选值,抛出错误。
// 没有 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"