• 前端基础 - 数据类型篇(高频面试!!!)


    数据类型

    在JavaScript中,数据类型可以分为两类:基础数据类型、引用/复杂数据类型

    1.基础类型:

    • String -> 表示文本类型,如 "Hello World!"

    • Number -> 表示数字,可以是整数或者浮点数,例如 3 或者 3.141592,在JavaScript中,所有数字都是浮点数类型,即使没有小数部分

    • Boolean -> 表示逻辑实体,只有两个值:truefalse

    • Undefined -> 表示表里已被声明但未赋值,或者直接没有被声明

    • Null -> 表示一个为空的值

    • BigInt(ES2020引入) -> 表示大于2^53 - 1的整数,这是Number类型能安全表示的最大整数。BigInt类型的值通过在整数后面加n来创建,例如 9007199254740991n

    • Symbol(ES6引入) --> 符号类型,表示唯一、不可变的数据值,常用于对象属性的键

    2.对象/复杂类型

    Object,表示一个实例对象,是键值队的集合。在JavaScript中,几乎所有事物都是对象,包括数组、函数等。

    • Function,特殊类型的对象,可调用,有时被视为一种数据结构,因为它们可以像对象一样具有属性和方法

    • Array,特殊类型的对象,用于存储数据集合跟列表

    此外,DateRegExp(正则表达式)、MapSetWeakMapWeakSet等都是特殊的对象类型,都可以用来存储和管理数据。


    下面重点说一下Symbol类型,面试爱问o(╥﹏╥)o

    1. 作为对象属性的键:

    使用Symbol创建的变量始终是唯一的,把它作为属性的键,可以有效避免冲突或者意外覆盖问题

    let price = {
        "影流之主": 6800,
        "影流之主": 4800,
    }
    console.log(price);//{ '影流之主': 4800 }
    
    //可以看到打印出来的对象只有一个属性,下面改写一下:
    
    const KEY_ONE = Symbol();
    const KEY_TWO = Symbol();
    let price2 = {
        [KEY_ONE]: 6800,
        [KEY_TWO]: 4800,
    };
    const MY_KEY = Symbol();
    price2[MY_KEY] = 3600;
    console.log(price2[KEY_ONE]);//6800
    console.log(price2);//{ [Symbol()]: 6800, [Symbol()]: 4800, [Symbol()]: 3600 }
    
    2. Symbol值的描述

    它可以接受一个字符串作为参数,并且通过description属性可以获取到对应的描述,进而区分不同的Symbol

    const MY_NAME = Symbol('MY_NAME');
    const YOUR_NAME = Symbol('YOUR_NAME');
    let person = {
        [MY_NAME]: '你比从前快乐KX',
        [YOUR_NAME]: '甜酒果子',
    }
    console.log(person[MY_NAME]);//你比从前快乐KX
    console.log(person[YOUR_NAME]);//甜酒果子
    console.log(MY_NAME.description);//MY_NAME
    console.log(YOUR_NAME.description);//YOUR_NAME
    
    //需要说明的是,带有相同参数的两个Symbol值不相等,这个参数只是表示Symbol值的描述而已
    
    const id1 = Symbol('id');
    const id2 = Symbol('id');
    console.log(id1 === id2);//false
    
    3. 隐藏属性

    使用Symbol创建的变量作为对象的属性,不能被常规方法访问到,所以可以使用这一点将属性隐藏,造成一个假的私有属性现象

    const MY_NAME = Symbol('MY_NAME');
    const YOUR_NAME = Symbol('YOUR_NAME');
    let person = {
        [MY_NAME]: '你比从前快乐KX',
        [YOUR_NAME]: '甜酒果子',
        'name': '张三',
    }
    console.log(Object.values(person));//[ '张三' ]
    console.log(Object.keys(person));//[ 'name' ]
    console.log(Object.getOwnPropertyNames(person));//[ 'name' ]
    for (const key in person) {
        console.log(key);//name
    }
    

    可以遍历到Symbol的方法:

    Object.getOwnPropertySymbols() :返回对象中只包含symbol类型key的数组

    Reflect.ownKeys() :返回对象中所有类型key的数组(包含symbol)

    console.log(Object.getOwnPropertySymbols(person));//[ Symbol(MY_NAME), Symbol(YOUR_NAME)
    console.log(Reflect.ownKeys(person));//[ 'name', Symbol(MY_NAME), Symbol(YOUR_NAME) ]
    
    4. Symbol自带的方法

    Symbol.for(),在全局 Symbol 注册表中搜索键为 key 的 Symbol。如果找到,则返回它;否则,将创建一个与给定键相关联的新 Symbol。这使得多个独立的代码片段可以通过给定的键共享 Symbol。

    Symbol.keyFor(),接受一个通过 Symbol.for 方法创建的 Symbol,并返回该 Symbol 注册表中的键。如果 Symbol 不是全局注册的,则返回 undefined。

    由于Symbol创建的值独一无二,但有时候我们可能希望使用同一个Symbol值,这时候就可以通过Symbol.for()创建

    const KEY1 = Symbol.for('KEY');
    const KEY2 = Symbol.for('KEY');
    console.log(KEY1 === KEY2);//true
    console.log(Symbol.keyFor(KEY1));//KEY
    console.log(Symbol.keyFor(KEY3));//undefined
    

    3. 包装类型

    在JavaScript中,包装类型(Wrapper Objects)不被视为独立的数据类型,而是存在于语言的运行时行为中,用于提供一种方式将原始数据类型(如 string、number、boolean、symbol、bigint)转换为对象。这样,原始值就可

    以像对象一样使用,访问方法和属性。如下:

    let heroName = 'LeBlanc';
    console.log(heroName.toLowerCase());//leblanc
    console.log(heroName.toString());//LeBlanc
    

    在上面的例子中,字符串 heroName 是一个原始类型的值。当调用 .toLowerCase() 方法时,JavaScript临时将 heroName 包装为一个 String 对象,以便可以访问 .toLowerCase() 方法。方法调用完成后,返回的是一个新的原始类型的字符串,而临时创建的包装对象被丢弃

    尽管包装对象在技术上不是JavaScript的基本数据类型,但它们是理解和使用语言中的原始值与对象之间互动的重要概念。然而,直接使用这些包装对象的构造函数来创建对象(例如,使用 new String("LeBlanc"))是不推荐的,因为它可能导致混淆和错误。在大多数情况下,最好让JavaScript自动处理原始值和对象之间的转换。


    另外,如果你尝试在原始值上设置一个属性,JavaScript 会创建一个临时对象,就像访问属性或方法时一样,但是设置的属性不会保留,因为这个临时对象会被立即丢弃

    这个行为可能初看起来有些反直觉。以下是一个例子来说明这个过程:

    let assassin = 'LeBlanc';
    assassin.chineseName = '乐芙兰';
    console.log(assassin);//LeBlanc
    console.log(assassin.chineseName);//undefined
    

    在这个例子中,assassin 是一个字符串,因此是一个原始值。当我们尝试给它设置 chineseName 属性时,JavaScript 会临时将 assassin 转换成一个 String 包装对象,并在这个对象上设置 chineseName 属性。但是,一旦这个操作完成,这个临时的包装对象就会被丢弃,所以 chineseName 并没有被真正添加到 assassin 上。当我们接下来尝试访问 assassin.chineseName 时,你会得到 undefined,因为 assassin 是一个原始值,它没有任何附加的属性。

    这也是为什么通常不建议在原始值上设置属性:这些属性不会被永久保存,因此这个操作没有任何实际效果。这个行为是 JavaScript 自动装箱机制的一部分,设计是为了让原始值表现得像对象一样,同时保持原始值的轻量和高效。

  • 相关阅读:
    web程序课程记录
    .NET8顶级调试lldb观察FOH堆字符串分配
    如何用MATLAB对CSI数据进行预处理(卡尔曼滤波篇)
    RPC(远程过程调用)
    java实现数据库自动异地备份
    弘辽科技:淘宝怎么才能获得更多流量?要做点什么?
    发布 VectorTraits v1.0,它是 C# 下增强SIMD向量运算的类库
    8 ICMP与ping
    惠普笔记本重装系统后没有声音如何解决
    NCP1256ESN65T1G具有多种保护功能 一款低功率离线电流模式PWM控制器
  • 原文地址:https://www.cnblogs.com/sweetdreamkx/p/18086807