Skip to content

新增数据类型

大整数 bigint

已有介绍。它可以表示大于 2**53 - 1 的整数

符号 Symbol

它是 ES6 新引入的一种原始数据类型。使用Symbol()可以直接生成一个新的值。

ES5 里面的对象的属性名是字符串,当我们使用别人的对象的时候,我不知道别人的对象有哪些属性,但是我又想添加一些新属性。如果直接写就有可能存在重名的情况,于是我们借助Symbol来生成一个独一无二的值,这样就可以防止属性名的冲突了。

javascript
let symbol = Symbol()
console.log(Symbol()) //Symbol()
typeof symbol //"symbol"

它不是一个构造函数,不能用new操作符。所以Symbol的值也不是一个对象,不能添加属性,可以理解为一个字符串的数据类型

Symbol的参数

字符串做参数:用于描述生成的Symbol方便自己区分生成的Symbol

javascript
let name = Symbol("name"),
    age1 = Symbol("age")
console.log(name, age1) //Symbol("name") Symbol("age")
name === age1 //false
let age2 = Symbol("age")
age1 === age2 //false
  • 打印的时候可以区分你用的是哪个值
  • 打印只是打印当前的Symbol的值的标识符,然而相同的标识符的Symbol是不一样的

对象做参数:虽然可以使用,但是Symbol本质内部对参数对象做了toString方法,还是字符串。

Symbol的计算问题

不能计算。除了toString和转布尔类型,因为本质上Symbol也是一个对象

javascript
let symbol = Symbol("1")
symbol.toString() //"Symbol(1)"
Boolean(symbol) //true
Number(symbol) //报错

Symbol作属性名

它的存在就是做一个属性名的

javascript
let obj = {},
    s1 = Symbol()
obj[s1] = "value of Symbol"
//或者
obj {
    [s1]: "value of Symbol"
}
//Object.defineProperty
Object.defineProperty(obj, s1, {
    value: "value of Symbol"
})
obj.s1 //等价于obj["s1"] undefined
obj[s1] //value of Symbol
obj[s1] = 123
javascript
var toString = Symbol("toString")
Object.prototype[toString] = function() {
    return 1
}
var a = {
    a: 1,
}
a.toString() //"[Object object]"
a[toString]() // 1

在对象内部定义Symbol属性的时候必须加方括号,不然解析会被认为是字符串。

Symbol作为属性名的遍历

for...infor...of都无法遍历到Symbol值的属性, Symbol值作为对象的属性也无法被Object.keys()Object.getOwnPropertyNames()来获取。
可以使用Object.getOwnPropertySymbols()来获取。

javascript
let s1 = Symbol("s1"),
    s2 = Symbol("s2")
let o = {}
o[s1] = "symbol s1"
o[s2] = "symbol s2"
o["s3"] = "s3"
for (let i in o) {
    console.log(i) //"s3"
}
Object.keys(o) //["s3"]
Object.getOwnPropertySymbols(o) //[Symbol(s1), Symbol(s2)]

Symbol.for()Symbol.keyFor()

Symbol.for接受一个字符串参数,查询有没有这个参数的Symbol值,
有的话就直接返回这个Symbol值,没有就返回一个这个参数的Symbol()

javascript
let s1 = Symbol("s1")
let s2 = Symbol.for("s2") //Symbol("s2")
s2 === Symbol.for("s2") //true

Symbol.keyFor函数是用来查询Symbol的登记状态的,如果没有就返回undefined,而Symbol.for会将生成的 Symbol 值登记到全局环境中,Symbol.keyFor会查询到Symbol.for函数生成的Symbol

javascript
let s1 = Symbol.for("s1"),
    s2 = Symbol.for("s2"),
    s3 = Symbol("s3"),
    s4 = Symbol("s4")

console.log(Symbol.keyFor(s1)) //"s1"
console.log(Symbol.keyFor(s2)) //"s2"
console.log(Symbol.keyFor(s3)) //undefined

内置的Symbol的值

Symbol 提供了 11 个内置的属性,分别是

  • Symbol.hasInstance

    • 使用instanceOf方法时调用此属性,判断某一对象是否是某构造函数的实例
    javascript
    class OneEnd {
        // 判断末尾是否为0
        static[Symbol.hasInstance](num) {
            return Number(num) % 10 == 1
        }
    }
    "123"
    instanceof ZeroEnd //false
        "1230"
    instanceof ZeroEnd //true
  • Symbol.isConcatSpreadable

    • 作为数组连接的时候是否允许展开,默认可以
    javascript
    let arr1 = [1, 2],
        arr2 = [3, 4]
    arr2[Symbol.isConcatSreadable] //undefined
    arr1.concat(arr2, 5) //[1, 2, 3, 4, 5]
    arr2[Symbol.isConcatSpreadable] = false
    arr1.concat(arr2, 5) //[1, 2, [3, 4], 5]
    arr2[Symbol.isConcatSpreadable] = true
    arr1.concat(arr2, 5) //[1, 2, 3, 4, 5]
  • Symbol.species

  • Symbol.match

  • Symbol.replace

  • Symbol.search

  • Symbol.split

  • Symbol.iterator

    指向默认遍历方法。见生成器函数章节

  • Symbol.toPrimitive

  • Symbol.toStringTag

    内置的 Object.prototype.toString() 方法会去读取这个返回

    javascript
    //基本类型即便没有 toStringTag 属性,也能被 toString() 方法识别并返回
    Object.prototype.toString.call([1, 2]) //"[object Array]"
    //非基本类型需要有toStringTag
    ;
    ({}).toString.call(function*() {}) //"[object GeneratorFunction]"
    //自己的类需要自己定义[Symbol.toStringTag]接口
    class ValidatorClass {
        get[Symbol.toStringTag]() {
            return "Validator"
        }
    }
  • Symbol.unscopables

集合 Set

Set 是一个构造函数,用来生成 Set 的数据结构,类似数组,但是成员值都是唯一的,没有重复

javascript
const s1 = new Set()[(1, 1, 1, 3, 2, 565, 76)].forEach((i) => s1.add(i))

for (let i of s1) {
    console.log(i)
}
//1, 3, 2, 565, 76
//解构
console.log([...s1]) //[1, 3, 2, 565, 76]
//接受数组参数新生成set
const s2 = new Set([1, 2, 3, 5])

数据去重简单做法

javascript
;
[...new Set(arr)] //

实例方法

  • add 添加元素,返回Set本身
  • size 返回实例成员长度
  • delete 删除某个具体的值,返回true或者false表示成败
  • clear 清空,无返回
  • has 查询参数是否是set的成员

Array.from()方法可以传入set实例对象转数组。

枚举方法

  • Set 数据类型有四个枚举方法,用于遍历成员。

    • keys: 返回枚举的键名,等价于键值
    • values: 返回枚举的键值
    • entries: 返回键值对的遍历器。
    • forEach: 使用回调函数遍历每一个成员
    javascript
    let set = new Set([1, 2, 3, 4])
    for (let i of set.keys()) console.log(i) //1 2 3 4
    for (let i of set.values()) console.log(i) //1 2 3 4
    for (let i of set.entries()) console.log(i) //[1, 1] [2, 2] [3, 3] [4, 4]
    set.forEach((i) => console.log(i)) //1 2 3 4

映射 Map

原生 JavaScript 的对象的本质就是一个由键与值的映射,值可以是任意数据类型,但是键只能是字符串。

es6 为了拓展键名的范围,使用了 Map,让键名成为复杂对象

javascript
let el = document.querySelector(".box"),
    map = new Map(),
    content = {
        description: "这是主要演示区域",
        belongTo: "page1",
        coder: "Gin",
    }
map.set(el, content) //返回Map对象
map.has(el) //true
map.has(content) //false
map.get(el) === content //true

示例方法

  • size 返回长度
  • set 设置映射关系,键名第一个参数,键值是第二个参数,返回本身
  • has 查询键名,返回布尔值
  • get 传入键名,返回键值,没有就是返回 undefined
  • delete 传入键名,返回布尔类型,失败是 false
  • clear 清空map

枚举方法

  • keys: 返回枚举的键名
  • values: 返回枚举的键值
  • entries: 返回键值对的枚举器。
  • forEach: 使用回调函数遍历每一个成员