likes
comments
collection
share

JavaScript中的类型判断(一)——原始类型和引用类型

作者站长头像
站长
· 阅读数 13

前言:

在本文中将主要对Symbol和BigInt以及注意事项多做讲解,在JavaScript中,有以下原始类型和引用类型:

一、原始类型与引用类型

  1. 原始类型(Primitive Types):

    • 字符串(String):例如:"Hello World"
    • 数字(Number):例如:42, 3.14
    • 布尔值(Boolean):例如:true, false
    • undefined:表示未定义的值
    • null:表示空值
    • Symbol:表示唯一的、不可变的值
    • BigInt:用于表示任意精度的整数,例如:123n
  2. 引用类型(Reference Types):

    • 对象(Object):例如:{name: "John", age: 25}
    • 数组(Array):例如:[1, 2, 3, 4]
    • 函数(Function):例如:function add(a, b) { return a + b; }
    • 正则表达式(Regular Expression):例如:^[0-9]*3$
类型输出:
let a = 123
let b = 'hello world'
let c = true
let u = undefined
let n = null
let s = Symbol(123)
let big = 123n  // bigInt

console.log(typeof a, typeof b, typeof c, typeof u, typeof n, typeof s, typeof big)
//输出:number string boolean undefined object symbol bigint
//对于null输出object类型是一个历史遗留问题,实际上null是一个特殊的原始类型
symbol类型:

Symbol是一种JavaScript的基本数据类型,引入于ES6(ECMAScript 2015)标准。它表示一个独一无二的值,即每个Symbol值都是唯一的,不会重复。

创建Symbol可以使用全局函数Symbol(),它可以接受一个可选的描述参数作为Symbol的标识符。这个描述参数仅用于调试和描述目的,不影响Symbol的唯一性。

下面是一个Symbol的示例:

//Symbol 创建独一无二的值
let s1 = Symbol('hello')
let s2 = Symbol('hello')
console.log(s1,s2)       //输出Symbol(hello) Symbol(hello)
console.log(s1 === s2);  //输出false

在上述示例中,我们创建了两个Symbol变量。我们可以通过typeof操作符验证s1和s2的类型为"symbol"。此外,我们还可以注意到s1和s2的值是唯一的,它们之间是不相等的。

Symbol经常用于对象属性的键,可以保证属性名的唯一性。例如:

const obj = {
  [Symbol("name")]: "John",
  [Symbol("age")]: 25,
  [Symbol("gender")]: "male"
};

console.log(Object.getOwnPropertySymbols(obj)); 
// 输出: [ Symbol(name), Symbol(age), Symbol(gender) ]

在这个例子中,我们使用Symbol作为对象obj的属性键,确保每个属性键都是唯一的。通过Object.getOwnPropertySymbols()方法,我们可以获取到对象obj所有Symbol类型的属性键。

需要注意的是,Symbol作为一种基本数据类型,它的值是不可变的,而且不能被强制转换为其他类型。因此,Symbol不能用于进行数学运算或字符串拼接等操作。它主要用于创建唯一的标识符,以及作为特定场景下的对象属性键。

BigInt类型:

BigInt类型用于表示任意精度的整数。BigInt类型的值可以通过在整数字面量后面加上字母"n"来创建,例如:let big = 123n。

BigInt类型可以存储超过JavaScript Number类型所能表示的范围的整数,它可以表示非常大或非常小的整数。BigInt类型的值可以进行基本的数学操作,如加法、减法、乘法和除法等。

let big = 123n; // 创建一个BigInt类型的值
console.log(typeof big); // 输出 "bigint"

let result = big + 1n; // 进行加法运算
console.log(result); // 输出 124n

// 将BigInt类型转换为Number类型进行计算
let converted = Number(big) + 1;
console.log(converted); // 输出 124

// BigInt类型与Number类型进行混合运算会导致精度损失
let mixed = big + 1; 
console.log(mixed); // 输出 124,但精度已损失
正则表达式:

下面是一个正则表达式的实例:假设要匹配一个字符串,这个字符串可以是任意长度的数字串,但是必须以数字"3"结尾。可以使用如下的正则表达式进行匹配:

^[0-9]*3$

这个正则表达式的含义是:

  • "^"表示匹配字符串的开头;
  • "[0-9]*"表示匹配任意长度的数字串;
  • "3"表示匹配数字"3";
  • "$"表示匹配字符串的结尾。

因此,这个正则表达式可以匹配任意长度的数字串,只要以数字"3"结尾即可。例如,可以匹配"123"、"4567893"、"33"等字符串,但是不能匹配"abc3"、"1a23"等非数字开头或者不以数字"3"结尾的字符串。

二、注意事项:

  • 原始类型是不可变的,一旦创建就无法修改。每次对原始类型的操作都会生成一个新的值。
  • 引用类型是可变的,可以添加、修改和删除其属性和方法。
  • 引用类型的赋值是按引用传递的,即复制的是对象的引用而非实际值。多个变量引用同一个对象时,改变其中一个变量的值会影响其他变量。
  • null表示空值,typeof null会返回"object",这是一个历史遗留问题,实际上null是一个特殊的原始类型。
  • undefined表示未定义的值,typeof undefined会返回"undefined"。
  • Symbol是ES6新增的原始类型,表示唯一的、不可变的值,可以用作对象的属性名。
  • BigInt类型只能进行与BigInt类型之间的运算,与其他原始类型(如Number)不能直接进行运算。
  • BigInt类型不能与Number类型进行混合运算,需要进行类型转换才能进行计算。
  • BigInt类型在进行比较操作时需要使用严格相等运算符(===),因为在相等比较时类型转换会导致精度损失。

三、需要注意的地方:

  • 原始类型在传递参数时是按值传递的,函数内部对参数的修改不会影响到外部变量。
  • 引用类型在传递参数时是按引用传递的,函数内部对参数的修改会影响到外部变量。
  • 在使用引用类型时要注意浅拷贝和深拷贝的问题(后文会做讲解),避免意外修改原始对象。
  • 对于字符串(String)、数字(Number)和布尔值(Boolean),尽量使用字面量的方式创建,而不是使用包装对象(String、Number、Boolean)。
  • 在判断变量的类型时,建议使用typeof运算符,但对于对象和数组,typeof都会返回"object",需要结合其他方式进行判断。