六种基本数据类型
undefined
null
string
boolean
number
symbol(ES6)
一种引用类型
Object
为什么要引入 Symbol?
ES5的对象中的属性名是字符串,容易造成属性名的冲突,如果有一种机制,保证每个属性的名字都是独一无二的,就可以从根本上防止属性名的冲突。
Symbol怎么生成?
symbol值通过Symbol函数生成,生成的symbol是一个类似于字符串的原始类型的值
const sym = Symbol(param); // param 可以为字符串或者对象
知识点:
1.使用new命令会报错,这是因为生成的Symbol是一个原始类型的值,不是对象,不能添加属性。
2.如果传入的参数为对象,会调用toString方法,再转为字符串
3.Symbol的值不能与其他的值进行运算,Symbol可以显式的转为字符串、布尔值,但不能转为数值。
4.Symbol函数的参数只是表示对当前 Symbol 值的描述,因此传入的参数不同,Symbol
的返回值也是不相等的。
Symbel值作为对象属性名时,怎样使用?
let mySymbol = Symbol(); // 第一种写法 let a = {}; a[mySymbol] = ‘Hello!‘; // 第二种写法 let a = { [mySymbol]: ‘Hello!‘ }; // 第三种写法 let a = {}; Object.defineProperty(a, mySymbol, { value: ‘Hello!‘ }); // 以上写法都得到同样结果 a[mySymbol] // "Hello!"
注意:Symbol
每一个值都是不相等的,意味着可以作为标识符,用于对象的属性名,能保证不会出现同名的属性,注意作为属性名时不能使用点运算符。
const mySymbol = Symbol(); const a = {}; a.mySymbol = ‘Hello!‘; a[mySymbol] // undefined a[‘mySymbol‘] // "Hello!" // a的属性名实际上是一个字符串而不是Symbol的值。
属性值的遍历
JSON.stringify
是在序列化过程中会自动转换成对应的原始值;Object.getOwnPropertySymbols
方法返回一个数组,成员是当前对象的所有用作属性名的 Symbol 值;Object.getOwnPropertyNames(obj)
一个对象,其自身的可枚举和不可枚举属性的名称被返回。keys
方法会返回一个由一个给定对象的自身可枚举属性组成的数组,数组中属性名的排列顺序和使用[for...in
]循环遍历该对象时返回的顺序一致 。Reflect.ownKeys
方法可以返回所有类型的键名,包括常规键名和 Symbol 键名。
obj // {ccc: "aaa", Symbol(a): "hello", Symbol(b): "world"}; JSON.stringify(obj) // "{"ccc":"aaa"}" Object.getOwnPropertyNames(obj) // ["ccc"] Object.keys(obj) // ["ccc"] Object.getOwnPropertySymbols(obj); // (2) [Symbol(a), Symbol(b)] Reflect.ownKeys(obj) // (3) ["ccc", Symbol(a), Symbol(b)]
如果我希望使用同一个Symbol值?
let s1 = Symbol.for(‘foo‘); let s2 = Symbol.for(‘foo‘); s1 === s2 // true
Symbol.for()
与Symbol()
这两种写法,都会生成新的 Symbol
。它们的区别是,前者会被登记在全局环境中供搜索,后者不会。
let s1 = Symbol.for("foo"); Symbol.keyFor(s1) // "foo" let s2 = Symbol("foo"); Symbol.keyFor(s2) // undefined
Symbol.keyFor
方法返回一个已登记的 Symbol 类型值的key。
注意:
- 需要注意的是,Symbol.for为 Symbol 值登记的名字,是全局环境的,可以在不同的 iframe 或 service worker 中取到同一个值。
内置的 Symbol 值?
Symbol.hasInstance
对象的Symbol.hasInstance属性,指向一个内部方法。当其他对象使用 instanceof
运算符,判断是否为该对象的实例时,会调用这个方法。比如, foo instanceof Foo
在语言内部,实际调用的是Foo[Symbol.hasInstance](foo)
。
class MyClass { [Symbol.hasInstance](foo) { return foo instanceof Array; } }
Symbol.isConcatSpreadable
对象的Symbol.isConcatSpreadable属性等于一个布尔值,表示该对象用于Array.prototype.concat()时,是否可以展开。
下面代码说明,Symbol.isConcatSpreadable默认等于 undefined
,可以展开。Symbol.isConcatSpreadable
= true
|| undefined
=> 展开Symbol.isConcatSpreadable
= false
=> 不展开
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‘]
类似数组的对象正好相反,默认不展开。它的Symbol.isConcatSpreadable属性设为true,才可以展开。
let obj = {length: 2, 0: ‘c‘, 1: ‘d‘}; [‘a‘, ‘b‘].concat(obj, ‘e‘) // [‘a‘, ‘b‘, obj, ‘e‘] obj[Symbol.isConcatSpreadable] = true; [‘a‘, ‘b‘].concat(obj, ‘e‘) // [‘a‘, ‘b‘, ‘c‘, ‘d‘, ‘e‘]
Symbol.species
对象的Symbol.species属性,指向一个构造函数。创建衍生对象时,会使用该属性。
原文地址:https://www.cnblogs.com/SallyShan/p/11625493.html