新增数据类型

1 Symbol

1.1 什么是Symbol

ES5 的对象属性名都是字符串,这容易造成属性名的冲突。比如,你使用了一个他人提供的对象,但又想为这个对象添加新的方法,新方法的名字就有可能与现有方法产生冲突。如果有一种机制,保证每个属性的名字都是独一无二的就好了,这样就从根本上防止属性名的冲突。这就是 ES6 引入Symbol的原因。

ES6 引入了一种新的原始数据类型Symbol,表示独一无二的值。它是 JavaScript 语言的第七种数据类型

1.2 Symbol的使用

  • Symbol 值通过Symbol函数生成。

  • 这就是说,对象的属性名现在可以有两种类型,一种是原来就有的字符串,另一种就是新增的 Symbol 类型。凡是属性名属于 Symbol 类型,就都是独一无二的,可以保证不会与其他属性名产生冲突

let s = Symbol();

typeof s
// "symbol"

let s1 = Symbol('foo');
let s2 = Symbol('bar');
s1 // Symbol(foo)
s2 // Symbol(bar)
s1.toString() // "Symbol(foo)"
s2.toString() // "Symbol(bar)"

1.3 Symbol表示独一无二的值

//1.之前出现的问题
/* let obj = {
      name: "lily",
      todo() {
         console.log("eat");
      }
}
//修改
obj.name = "xiaowang";
obj.todo = () => {
     console.log("someThing~")
}
console.log(obj.name);
obj.todo(); */

//需求:让新增的属性和方法不和之前的冲突
let name = Symbol("name");
let todo = Symbol("todo");
let obj = {
    name: "小王"
}
obj[name] = "老王"

console.log(obj);
console.log(obj.name)
console.log(obj[name])

1.4 Symbol的注意事项

  • Symbol中传入的字符串没有任何意义,只是用来描述Symbol的

    {
        let obj1 = {
            name: "lily",//原有对象拥有name属性
            age: 18,
        }
        let name = Symbol("name");
        let age = Symbol("age");
        obj1[name] = "xiaowang";
        obj1[age] = 21;
        console.log(obj1)
    }
  • Symbol不能使用New调用

    new Symbol();//Symbol is not a constructor
  • 类型转换的时候,不能转数字

    console.log(String(Symbol("a")));//Symbol(a)
    console.log(Boolean(Symbol()));//true
    // console.log(Symbol() + 1);//Cannot convert a Symbol value to a number
    // console.log(Number(Symbol()));//Cannot convert a Symbol value to a number
  • 如果把Symbol当作一个对象的属性和方法的时候,一定要用一个变量来储存,否则定义的属性和方法没有办法使用

    {
        let obj = {
            name: "lily",//原有对象拥有name属性
            age: 18,
        }
        obj[Symbol()] = "再见";//如果直接设置,则再也获取不到这个属性了
        console.log(obj);
    
        console.log(obj[Symbol()])//undefined
    }
  • for in 不能遍历出来,可以使用Object.getOwnPropertySymbols方法来拿

    {
        let obj = {
            name: "lily",//原有对象拥有name属性
            age: 18,
        }
        let name = Symbol();
        obj[name] = "再见";//如果直接设置,则再也获取不到这个属性了
    
        for (let i in obj) {
            console.log(i);
        }
    
        //可以使用 Object.getOwnPropertySymbols方法来拿
        console.log(Object.getOwnPropertySymbols(obj));//[Symbol()]
    }

2 BigInt

  • JavaScript 所有数字都保存成 64 位浮点数,这给数值的表示带来了两大限制。一是数值的精度只能到 53 个二进制位(相当于 16 个十进制位),大于这个范围的整数,JavaScript 是无法精确表示的,这使得 JavaScript 不适合进行科学和金融方面的精确计算。二是大于或等于2的1024次方的数值,JavaScript 无法表示,会返回Infinity

  • 引入了一种新的数据类型 BigInt(大整数),来解决这个问题。BigInt 只用来表示整数,没有位数的限制,任何位数的整数都可以精确表示。

    // 超过 53 个二进制位的数值,无法保持精度
    Math.pow(2, 53) === Math.pow(2, 53) + 1 // true
    
    // 超过 2 的 1024 次方的数值,无法表示
    Math.pow(2, 1024) // Infinity
    
    
    const a = 2172141653n;
    const b = 15346349309n;
    // BigInt 可以保持精度
    a * b // 33334444555566667777n
    
    // 普通整数无法保持精度
    Number(a) * Number(b) // 33334444555566670000
  • 为了与 Number 类型区别,BigInt 类型的数据必须添加后缀n

    1234 // 普通整数
    1234n // BigInt
    
    // BigInt 的运算
    1n + 2n // 3n
  • BigInt 与普通整数是两种值,它们之间并不全等。

    42n === 42 // false
  • typeof运算符对于 BigInt 类型的数据返回bigint

posted @ 2023-01-29 13:27  z_bky  阅读(33)  评论(0)    收藏  举报