likes
comments
collection
share

你真的会类型判断?我不信

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

Symbol

Symbol 是 JavaScript 中的一种基本数据类型,它在 ES6(ECMAScript 2015)中被引入。Symbol 可以用来创建唯一的标识符,这些标识符在整个程序中是唯一的。

Symbol 值是不可变且唯一的,因此可以用作对象属性的键。这样就可以确保对象属性的唯一性,避免命名冲突。

要创建一个 Symbol,可以使用全局的 Symbol 函数,并且可以传入一个可选的描述参数。例如:

javascriptCopy Code
const s1 = Symbol(); // 创建一个没有描述的 Symbol

const s2 = Symbol('description'); // 创建一个带有描述的 Symbol

在上面的代码中,s1s2 都是独一无二的 Symbol,他们不相等。

Symbol 还有一些内置的属性,比如 Symbol.iteratorSymbol.toStringTag 等,它们提供了对对象的不同行为进行自定义的能力。

除了创建独特的标识符外,Symbol 还有一些静态方法和实例方法可以使用。其中一些常用的方法包括:

  • Symbol.for(key):通过全局的 Symbol 注册表,返回一个具有给定 key 的共享 Symbol。如果注册表中存在该 key 对应的 Symbol,则返回已存在的 Symbol;否则,创建一个新的 Symbol 并将其存储在注册表中。
  • Symbol.keyFor(symbol):返回与给定 Symbol 相关联的键(如果存在于全局注册表中)。否则,返回 undefined。

Symbol 还可以与其他数据类型一起使用,比如作为对象属性名、作为迭代器对象的标识等等。

需要注意的是,由于 Symbol 是不可变且唯一的,所以无法通过常规手段改变或重写一个 Symbol。

BigInt

BigInt 是 JavaScript 中的一种内置数据类型,它用于表示任意精度的整数。BigInt 可以表示比 Number 类型更大范围的整数,而且不会发生溢出。

在 JavaScript 中,普通的 Number 类型使用 64 位双精度浮点数表示,因此有一个固定的范围,即 -(2^53 - 1) 到 2^53 - 1。超出该范围的整数将无法精确表示。

为了解决这个限制,ES2020 引入了 BigInt 类型。BigInt 使用后缀 "n" 或调用 BigInt() 函数来创建。

下面是一些创建 BigInt 的示例:

const bigInt1 = 1234567890123456789012345678901234567890n;
const bigInt2 = BigInt(9007199254740991); // 使用 BigInt() 函数创建

console.log(bigInt1); // 输出:1234567890123456789012345678901234567890n
console.log(bigInt2); // 输出:9007199254740991n

BigInt 支持与其他 BigInt 进行算术运算和比较操作,以及与 Number 类型之间的转换。需要注意的是,BigInt 类型和 Number 类型不能直接进行混合运算,需要通过 BigInt() 或 Number() 函数进行转换。

下面是一些 BigInt 的运算示例:

const bigInt1 = 10n;
const bigInt2 = BigInt(5);
const result = bigInt1 + bigInt2;

console.log(result); // 输出:15n
console.log(result === 15); // 输出:false
console.log(Number(result)); // 输出:15

需要注意的是,BigInt 类型不能与 Number 类型之间直接进行比较操作,因为它们属于不同的数据类型。如果需要比较 BigInt 和 Number,可以先使用 BigInt() 或 Number() 函数将它们转换为相同的类型。

BigInt 的引入为 JavaScript 提供了处理大整数运算的能力,尤其在涉及加密、大数字计算和精确数值计算等方面非常有用。

BigInt 函数

简单的 JavaScript BigInt 函数,它实现了 BigInt 类型的基本算术运算和比较操作:

function bigInt(str) {
  if (typeof str !== 'string') {
    throw new Error('Input must be a string');
  }

  // 判断是否为负数,并去掉符号
  const isNegative = str.startsWith('-');
  const digits = [...str.replace('-', '')].map(Number);

  let result = BigInt(0);
  let multiplier = BigInt(1);

  // 从右向左遍历字符串中的数字,计算 BigInt 值
  for (let i = digits.length - 1; i >= 0; i--) {
    const digit = digits[i];
    const addend = BigInt(digit) * multiplier;
    result += addend;
    multiplier *= BigInt(10);
  }

  // 如果是负数,则取反
  if (isNegative) {
    result = -result;
  }

  return result;
}

这个函数接受一个字符串作为参数,返回一个 BigInt 类型的值。它首先判断输入是否为字符串,然后根据字符串中的数字和符号计算 BigInt 值。

在计算 BigInt 值时,我们可以使用 BigInt() 函数将数字转换为 BigInt 类型,并使用 * 运算符进行乘法运算。由于 BigInt 类型支持任意位数的整数,因此我们可以从右向左遍历字符串中的数字,并用一个乘数(初始值为 1)来计算每个数字对应的 BigInt 值,最终将它们相加得到结果。

除了基本的算术运算外,BigInt 还支持比较操作,例如 ><>=<===!=。我们可以使用这些操作符来实现 BigInt 的比较:

function compareBigInt(a, b) {
  if (a > b) {
    return 1;
  } else if (a < b) {
    return -1;
  } else {
    return 0;
  }
}

console.log(compareBigInt(bigInt('1234567890123456789012345678901234567890'), bigInt('9876543210987654321098765432109876543210'))); // 输出:-1

在上面的代码中,compareBigInt 函数接受两个 BigInt 类型的参数,并返回它们之间的比较结果。我们可以使用 ><== 运算符来实现比较。如果 a 大于 b,则返回 1;如果 a 小于 b,则返回 -1;如果 a 等于 b,则返回 0。

需要注意的是,在进行任何计算或比较操作之前,我们需要使用 BigInt() 函数将数字转换为 BigInt 类型。同时,我们也需要注意 BigInt 类型和 Number 类型之间的转换,以避免精度丢失。

typeof无法判断

在 JavaScript 中,有一些类型无法使用 typeof 运算符来进行判断。以下是其中的几种类型:

  1. nulltypeof null 的结果是 "object"。这是一个历史遗留问题,因为在 JavaScript 的早期版本中,null 被错误地标记为一个对象。虽然这个问题已经得到了修复,但为了保持兼容性,typeof null 仍然返回 "object"
  2. NaNtypeof NaN 的结果是 "number"。虽然 NaN 表示一个非数字值,但它的类型仍然是 Number。如果需要检查一个值是否为 NaN,可以使用 isNaN() 函数。
  3. Symboltypeof Symbol('foo') 的结果是 "symbol"Symbol 是一种新的基本数据类型,用于表示唯一的标识符。它不能通过任何函数或运算符转换为其他类型。
  4. BigInt:在旧版的 JavaScript 中,BigInt 类型并不存在,因此 typeof BigInt(42) 的结果是 "undefined"。但在现代的浏览器中,BigInt 已成为 ECMAScript 标准的一部分,可以用于处理超出 Number 范围的整数。

除了上述类型外,JavaScript 中的所有值都可以使用 typeof 运算符来进行判断。需要注意的是,typeof 运算符只能用于判断原始数据类型(例如字符串、数字、布尔值、undefined 和 symbol),而不能用于判断对象、数组或函数等复杂数据类型。如果需要检查一个值是否为对象、数组或函数,可以使用 Array.isArray()Object.prototype.toString.call() 或其他相关的函数进行判断。

判断引用类型:instanceof

在 JavaScript 中,instanceof 运算符用于检查一个对象是否属于某个特定类或构造函数的实例。它的语法如下:

object instanceof constructor

其中,object 是要检查的对象,constructor 是要检查的类或构造函数。

以下是一些示例:

class Person {}
const person = new Person();
console.log(person instanceof Person); // true,person 是 Person 类的实例


const array = [];
console.log(array instanceof Array); // true,array 是 Array 类的实例
console.log(array instanceof Object); // true,array 也是 Object 类的实例,因为 Array 继承自 Object


const obj = {};
console.log(obj instanceof Object); // true,obj 是 Object 类的实例


let fn = function(){}
console.log(fn instanceof Object); // true,fn 是 Object 类的实例


const num = 123;
console.log(num instanceof Number); // false,num 不是 Number 类的实例,因为 num 是原始数据类型而不是 Number 对象

通过原型链判断是否是引用类型的代码:

function myInstance(left,right){
     left = left.__proto__
     right= right.prototype
    while(left !=null){
        if(left === right){
            return true
        }
        left = left.__proto__
    }
    return false

}
console.log(myInstance([],String));  //false

需要注意的是,instanceof 运算符主要适用于检查对象是否是由特定类或构造函数创建的实例。它并不适用于原始数据类型的检查,因为原始数据类型不是对象。对于原始数据类型,可以使用对应的包装对象来进行检查,例如 NumberStringBoolean 等。

另外,instanceof 运算符也无法检查自定义的原始构造函数。如果要检查自定义的构造函数,可以使用其他方式,例如比较原型链或使用 Object.prototype.isPrototypeOf() 方法。

Object.prototype.toString()

在 JavaScript 中,Object.prototype.toString() 方法返回一个表示当前对象的字符串。这个方法通常被用来判断一个对象的类型。

当 Object.prototype.toString() 方法被调用时,它会先检查调用它的对象的类型,然后返回一个以 "[object " 开头,以 "]" 结尾的字符串。

例如,对于一个空数组,调用 Object.prototype.toString() 方法返回的字符串会是 "[object Array]"。同样地,对于一个字符串,返回的字符串是 "[object String]"。因此,可以使用这个方法来判断一个对象的类型,例如:

const myArray = [1, 2, 3];
console.log(Object.prototype.toString.call(myArray)); // 输出: "[object Array]"

const myString = "hello";
console.log(Object.prototype.toString.call(myString)); // 输出: "[object String]"

1. 如果this值未定义则返回

![image.png](https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/eff2e5d36bb3401190180467d7a4117c~tplv-k3u1fbpfcp-jj-mark:0:0:0:0:q75.image#?w=352&h=44&s=3702&e=png&b=fffefe)

2. 如果this值为null则返回

你真的会类型判断?我不信

3. 设O是 ToObject(this),如果你传的是原始类型,那就会调用ToObject将原始类型转换成对象

你真的会类型判断?我不信

Object.prototype.toString() 方法可以用来判断对象的类型,但它并不完全可靠。例如,如果你使用它来判断一个自定义类的类型,返回的字符串可能只是 "[object Object]",并不能准确地表示这个对象的类型。因此,在实际开发中,建议使用更具体的方法来判断对象的类型。

Array.isArray()

在 JavaScript 中,Array.isArray() 是一个用来判断一个值是否为数组的方法。这个方法返回一个布尔值,如果给定的值是一个数组,则返回 true,否则返回 false。

Array.isArray() 方法对于区分数组和其他类型的对象非常有用,因为在 JavaScript 中,使用 typeof 操作符来检查数组会返回 "object",而不会返回 "array"。因此,为了准确地判断一个值是否为数组,就需要使用 Array.isArray() 方法。

以下是 Array.isArray() 方法的示例用法:

const arr = [1, 2, 3];
console.log(Array.isArray(arr)); // 输出: true

const obj = { key: 'value' };
console.log(Array.isArray(obj)); // 输出: false

const str = 'hello';
console.log(Array.isArray(str)); // 输出: false

在上面的示例中,Array.isArray() 方法被用来判断不同类型的值是否为数组。对于数组 arr,返回 true;对于普通对象 obj 和字符串 str,都返回 false。

注意,Array.isArray是构造函数调用的

总之,Array.isArray() 方法是用来确定一个值是否为数组的最佳方式,它能够更精确地区分数组和其他类型的对象。