ES6 数据类型Symbol(唯一)

数据类型

目录

  • 数据类型
    • 数据分类
    • Symbol 数据类型
      • 概述
      • 作为属性名
      • 属性名的遍历
      • 定义一个私有属性
      • 定义一个私有方法
      • Symbol.for(),Symbol.keyFor()
      • 其他方法详解
    • BigInt 数据类型
      • 为什么要引入?
      • BigInt 对象

数据分类

  • 基本类型: 直接存取基本类型

    • 字符串
    • 数值
    • 布尔类型
    • null
    • undefined
    • Symbol(ES6)
    • BigInt(ES2020)
  • 复杂类型: 通过引用的方式存取复杂类型

    • 对象
    • 数组
    • 函数
      回到顶部 目录

Symbol 数据类型

概述

为什么要引入该数据类型:

ES5 的对象属性名都是字符串,这容易造成属性名的冲突

Symbol:表示独一无二的值,最大的用法是用来定义对象的唯一属性名,而且它是一个值类型。

let sym1 = Symbol();
let sym2 = Symbol();

console.log(sym1)  // Symbol()
console.log(typeof sym1)  // 'symbol'
console.log(sym1 == sym2) // false
console.log(sym1 === sym2) // false

Symbol函数可以接受一个字符串作为参数,表示对 Symbol 实例的描述

主要是为了在控制台显示,或者转为字符串时,比较容易区分

let s1 = Symbol('foo');
let s2 = Symbol('bar');

console.log(s1) // Symbol(foo)
console.log(s2) // Symbol(bar)
console.log(s1.toString()) // "Symbol(foo)"
console.log(s2.toString() )// "Symbol(bar)"
  • Symbol 值不能与其他类型的值进行运算,会报错
  • Symbol 值可以显式转为字符串、也可以转为布尔值,但是不能转为数值
  • 在ES2019中增加了一个description可用于读取Symbol的描述.description

作为属性名

Symbol具有唯一性,用于对象的属性名,就能保证不会出现同名的属性

const my = Symbol();
const s = Symbol();

// 1
const a = {};
a[my] = 'hello';

// 2
const b = {
    [my]: 'hello',
    [s](arg) { ... }
};

// 3
const c = {};
Object.defineProperty(a, my, {value: 'hello'});
  • Symbol 值作为对象属性名时,不能用点运算符
  • Symbol 值作为属性名时,该属性还是公开属性,不是私有属性

属性名的遍历

Symbol 作为属性名不会被查询的几种方法:

  • for…in、for…of循环中
  • Object.keys()
  • Object.getOwnPropertyNames()
  • JSON.stringify()

Symbol 作为属性名可以被获取的方法:

  • Object.getOwnPropertySymbols()方法

    该方法返回一个数组,成员是当前对象的所有用作属性名的 Symbol 值

  • Reflect.ownKeys()方法可以返回所有类型的键名,包括常规键名和 Symbol 键名

回到顶部 目录

定义一个私有属性

let size = Symbol('size');

class Count{
    constructor(){
        this[size] = 0;
    }
    add(item){
        this[this[size]] = item;
        this[size] ++;
    }
    static sizeOf(instance){
        return instance[size];
    }
}

let x = new Count();
console.log(Count.sizeOf(x));// 0

x.add('foo');
console.log(Count.sizeOf(x));// 1

console.log(Object.keys(x)); // ["0"]
console.log(Object.getOwnPropertyNames(x));// ["0"]
console.log(Object.getOwnPropertySymbols(x));// [Symbol(size)]

// 对象x的size属性是一个 Symbol 值,所以Object.keys(x)、Object.getOwnPropertyNames(x)都无法获取它。这就造成了一种非私有的内部方法的效果

定义一个私有方法

const Hero = (() =>{
    const getRandom = Symbol()   //计算属性名
    return class{
    
        constructor(attack,hp,defence){
            this.attack = attack;
            this.hp = hp;
            this.defence;
        }
        gongji(){
            const dmg = this.attack * this[getRandom](0.7,1.2);
            console.log(dmg)
        }
        [getRandom](min,max){
            return Math.random() * (max - min) + min;
        }
    }
})();
const h = new Hero(3,100,3);
console.log(h)

Symbol.for(),Symbol.keyFor()

  • Symbol.for(): 重新使用同一个 Symbol 值

    它接受一个字符串作为参数,然后搜索有没有以该参数作为名称的 Symbol 值。如果有,就返回这个 Symbol 值,否则就新建一个以该字符串为名称的 Symbol 值,并将其注册到全局

let s1 = Symbol.for('foo');
let s2 = Symbol.for('foo');

s1 === s2 // true
  • Symbol.keyFor()方法返回一个已登记的 Symbol 类型值的key
let s1 = Symbol.for("foo");
Symbol.keyFor(s1) // "foo"

let s2 = Symbol("foo");
Symbol.keyFor(s2) // undefined

注意,Symbol.for()为 Symbol 值登记的名字,是全局环境的,不管有没有在全局环境运行

其他方法详解

补充一个运算符:**(指数运算符)

回到顶部 目录

BigInt 数据类型

为什么要引入?

  1. JavaScript 所有数字都保存成 64 位浮点数,这给数值的表示带来了两大限制(数值太小会失去精准度)
  2. 大于或等于2的1024次方的数值,JavaScript无法表示,会返回Infinity(无限大)
  3. 为了适合进行科学和金融方面的精确计算
// 超过 53 个二进制位的数值,无法保持精度
Math.pow(2, 53) === Math.pow(2, 53) + 1 // true

// 超过 2 的 1024 次方的数值,无法表示
Math.pow(2, 1024) // Infinity
  1. BigInt:类型的数据必须添加后缀n
  2. BigInt:与普通整数是两种值,它们之间并不相等
  3. typeof BigInt类型的数据 == bigint
  4. BigInt:基本上Number差不多,就是一个升级版

BigInt 对象

BigInt(123) //==> 123n

  • BigInt()构造函数必须有参数,而且参数必须可以正常转为数值
  • 参数如果是小数,也会报错
  • 用new关键字也会报错

计算:

  • BigInt 类型的除法会省略小数
  • BigInt 不能与普通数值进行混合运算
  • BigInt 其他的和number都一样

回到顶部 目录

你可能感兴趣的:(#,ES6,javascript,es6,js)