当前位置: 首页 > article >正文

js数据类型全解析,怎么区分呢?

在JavaScript里,数据类型就像是不同类型的“小盒子”,每个“小盒子”装的数据都有自己的特点,区分它们能帮助我们在编程时正确处理数据。下面用大白话给你讲讲常见的数据类型以及区分方法,还会配上代码示例。

  1. 基本数据类型
    • 数字(number:就是我们平常说的各种数字,像整数1、2、3,小数3.14等都属于这个类型。在JavaScript里,它还能表示特殊值,比如NaN(表示不是一个数字,像0除以0的结果),Infinity(无穷大,比如1除以0的结果) 。
    let num1 = 5;
    let num2 = 3.14;
    let num3 = NaN;
    let num4 = Infinity;
    console.log(typeof num1); // 输出 "number"
    console.log(typeof num2); // 输出 "number"
    console.log(typeof num3); // 输出 "number"
    console.log(typeof num4); // 输出 "number"
    
    • 字符串(string:就是用单引号''、双引号""或模板字符串``括起来的内容,比如'Hello'"world"、`Hello, ${name}`(模板字符串可以嵌入变量) 。
    let str1 = '这是一个字符串';
    let str2 = "也可以用双引号";
    let name = '张三';
    let str3 = `你好,${name}`;
    console.log(typeof str1); // 输出 "string"
    console.log(typeof str2); // 输出 "string"
    console.log(typeof str3); // 输出 "string"
    
    • 布尔值(boolean:只有两个值,true(表示真)和false(表示假) ,常用来做判断。
    let bool1 = true;
    let bool2 = false;
    console.log(typeof bool1); // 输出 "boolean"
    console.log(typeof bool2); // 输出 "boolean"
    
    • 空值(null:表示一个“空”的对象指针,它只有一个值null,就好像一个空盒子,等着装对象,但现在还没装。
    let n = null;
    console.log(typeof n); // 输出 "object",这是JavaScript的一个历史遗留问题,实际上它是null类型
    
    • 未定义(undefined:当一个变量声明了但没有赋值时,它的值就是undefined,表示“未定义” 。
    let var1;
    console.log(var1); // 输出 undefined
    console.log(typeof var1); // 输出 "undefined"
    
    • 符号(symbol:是ES6新增的基本数据类型,每个symbol值都是唯一的,常用来创建对象的唯一属性。
    let sym1 = Symbol('描述');
    let sym2 = Symbol('描述');
    console.log(sym1 === sym2); // 输出 false
    console.log(typeof sym1); // 输出 "symbol"
    
    • 大整数(bigint:用来表示大于Number.MAX_SAFE_INTEGER(最大安全整数)的整数,在数字后面加n表示。
    let bigInt1 = 12345678901234567890n;
    console.log(typeof bigInt1); // 输出 "bigint"
    
  2. 引用数据类型
    • 对象(object:可以理解为一个“大容器”,用来存放各种相关的数据和功能(方法) 。对象由键值对组成,键就像“小抽屉”的名字,值就是放在“小抽屉”里的东西。
    let person = {
        name: '李四',
        age: 20,
        sayHello: function() {
            console.log('你好,我是'+ this.name);
        }
    };
    console.log(typeof person); // 输出 "object"
    person.sayHello(); // 输出 "你好,我是李四"
    
    • 函数(function:是一种特殊的对象,它可以被调用执行一些操作。函数可以接收参数,也可以返回值。
    function add(a, b) {
        return a + b;
    }
    console.log(typeof add); // 输出 "function"
    let result = add(3, 5);
    console.log(result); // 输出 8
    
  3. 区分数据类型的方法
    • typeof操作符:这是最常用的区分数据类型的方法,但它对null的判断有个“小坑” 。它会返回一个字符串,表明数据的类型。
    let num = 10;
    let str = 'test';
    let bool = true;
    let obj = { key: 'value' };
    let func = function() {};
    let nul = null;
    console.log(typeof num); // 输出 "number"
    console.log(typeof str); // 输出 "string"
    console.log(typeof bool); // 输出 "boolean"
    console.log(typeof obj); // 输出 "object"
    console.log(typeof func); // 输出 "function"
    console.log(typeof nul); // 输出 "object",实际是null类型
    
    • instanceof操作符:主要用来判断一个对象是否是某个构造函数的实例,也就是判断对象的类型。它不适用于基本数据类型(除了StringNumberBoolean这些包装对象) 。
    let arr = [1, 2, 3];
    console.log(arr instanceof Array); // 输出 true
    let date = new Date();
    console.log(date instanceof Date); // 输出 true
    
    • Object.prototype.toString.call()方法:这是一种更准确的判断数据类型的方法,它可以正确区分各种数据类型,包括nullundefined
    let num = 10;
    let str = 'test';
    let bool = true;
    let obj = { key: 'value' };
    let func = function() {};
    let nul = null;
    let und = undefined;
    console.log(Object.prototype.toString.call(num)); // 输出 "[object Number]"
    console.log(Object.prototype.toString.call(str)); // 输出 "[object String]"
    console.log(Object.prototype.toString.call(bool)); // 输出 "[object Boolean]"
    console.log(Object.prototype.toString.call(obj)); // 输出 "[object Object]"
    console.log(Object.prototype.toString.call(func)); // 输出 "[object Function]"
    console.log(Object.prototype.toString.call(nul)); // 输出 "[object Null]"
    console.log(Object.prototype.toString.call(und)); // 输出 "[object Undefined]"
    

除了基本数据类型,JavaScript还有哪些数据类型?

1. 对象(Object)

对象是 JavaScript 中最常用的引用数据类型之一,可以把它想象成一个“容器”,用于存储各种数据和功能。它由键值对组成,键是字符串(ES6 开始也可以是 Symbol 类型),值可以是任意数据类型,包括基本数据类型和其他引用数据类型。

代码示例

// 创建一个对象
const person = {
    name: '张三',
    age: 25,
    hobbies: ['阅读', '跑步'],
    sayHello: function() {
        console.log(`你好,我是 ${this.name},今年 ${this.age} 岁。`);
    }
};

// 访问对象的属性
console.log(person.name); // 输出: 张三

// 调用对象的方法
person.sayHello(); // 输出: 你好,我是 张三,今年 25 岁。

2. 数组(Array)

数组是一种特殊的对象,用于存储有序的数据集合。数组中的每个元素都有一个对应的索引,索引从 0 开始。可以通过索引来访问、修改或删除数组中的元素。

代码示例

// 创建一个数组
const numbers = [1, 2, 3, 4, 5];

// 访问数组元素
console.log(numbers[2]); // 输出: 3

// 修改数组元素
numbers[3] = 10;
console.log(numbers); // 输出: [1, 2, 3, 10, 5]

// 数组的一些常用方法
numbers.push(6); // 在数组末尾添加元素
console.log(numbers); // 输出: [1, 2, 3, 10, 5, 6]

const poppedElement = numbers.pop(); // 移除数组末尾的元素
console.log(poppedElement); // 输出: 6
console.log(numbers); // 输出: [1, 2, 3, 10, 5]

3. 函数(Function)

函数也是一种引用数据类型,它可以被看作是一段可重复使用的代码块。函数可以接收参数,执行特定的操作,并返回一个值。

代码示例

// 定义一个函数
function add(a, b) {
    return a + b;
}

// 调用函数
const result = add(3, 5);
console.log(result); // 输出: 8

// 函数可以作为参数传递给其他函数
function multiplyByTwo(num) {
    return num * 2;
}

function processNumber(num, callback) {
    return callback(num);
}

const processedResult = processNumber(4, multiplyByTwo);
console.log(processedResult); // 输出: 8

4. 日期(Date)

Date 对象用于处理日期和时间。可以使用 new Date() 来创建一个表示当前日期和时间的对象,也可以传入特定的参数来创建指定日期和时间的对象。

代码示例

// 创建一个表示当前日期和时间的对象
const currentDate = new Date();
console.log(currentDate); // 输出当前日期和时间

// 创建一个指定日期的对象
const specificDate = new Date('2024-10-01');
console.log(specificDate); // 输出: 2024-10-01T00:00:00.000Z

// 获取日期的各个部分
const year = specificDate.getFullYear();
const month = specificDate.getMonth() + 1; // 月份从 0 开始,所以要加 1
const day = specificDate.getDate();
console.log(`日期是 ${year}${month}${day}`); // 输出: 日期是 2024 年 10 月 1 日

5. 正则表达式(RegExp)

正则表达式用于匹配和处理字符串。可以使用正则表达式来验证字符串的格式、查找特定的字符模式等。

代码示例

// 创建一个正则表达式对象
const pattern = /abc/;

// 测试字符串是否匹配正则表达式
const str1 = 'abcdef';
const str2 = 'defabc';
const str3 = 'defghi';

console.log(pattern.test(str1)); // 输出: true
console.log(pattern.test(str2)); // 输出: true
console.log(pattern.test(str3)); // 输出: false

// 使用正则表达式替换字符串中的内容
const replacedStr = str1.replace(pattern, 'xyz');
console.log(replacedStr); // 输出: xyzdef

6. 集合(Set)和映射(Map)

  • SetSet 对象是一种无序且唯一的数据集合。它类似于数组,但每个元素都是唯一的,不会有重复的值。
  • MapMap 对象是一种键值对的集合,其中键和值可以是任意数据类型,并且键是唯一的。

代码示例

// 使用 Set
const mySet = new Set([1, 2, 3, 2, 4]);
console.log(mySet); // 输出: Set(4) { 1, 2, 3, 4 }

// 检查元素是否存在
console.log(mySet.has(3)); // 输出: true

// 添加元素
mySet.add(5);
console.log(mySet); // 输出: Set(5) { 1, 2, 3, 4, 5 }

// 使用 Map
const myMap = new Map();
myMap.set('name', '李四');
myMap.set('age', 30);

// 获取元素
console.log(myMap.get('name')); // 输出: 李四

// 检查键是否存在
console.log(myMap.has('age')); // 输出: true

这些引用数据类型在 JavaScript 中非常重要,它们各自具有不同的特点和用途,可以帮助我们更高效地处理和组织数据。

如何判断一个变量的数据类型

1. typeof 操作符

  • 原理typeof 是一个一元操作符,它返回一个表示数据类型的字符串。可以快速判断基本数据类型,但对于一些引用数据类型的判断不够细致。
  • 适用场景:适用于判断基本数据类型(如 numberstringbooleanundefinedsymbolbigint),以及区分函数和其他引用数据类型。
  • 代码示例
let num = 10;
let str = 'hello';
let bool = true;
let undef;
let sym = Symbol('test');
let big = 12345678901234567890n;
let func = function() {};
let obj = {};

console.log(typeof num); // 输出: "number"
console.log(typeof str); // 输出: "string"
console.log(typeof bool); // 输出: "boolean"
console.log(typeof undef); // 输出: "undefined"
console.log(typeof sym); // 输出: "symbol"
console.log(typeof big); // 输出: "bigint"
console.log(typeof func); // 输出: "function"
console.log(typeof obj); // 输出: "object"
  • 局限性typeof null 返回 "object",这是 JavaScript 的一个历史遗留问题;对于数组、日期等引用数据类型,typeof 都返回 "object",无法进一步区分具体类型。

2. instanceof 操作符

  • 原理instanceof 用于判断一个对象是否是某个构造函数的实例。它会检查对象的原型链中是否存在该构造函数的 prototype 属性。
  • 适用场景:适用于判断对象是否为某个特定类的实例,常用于自定义类或内置对象(如 ArrayDate 等)的判断。
  • 代码示例
let arr = [1, 2, 3];
let date = new Date();
let obj = {};

console.log(arr instanceof Array); // 输出: true
console.log(date instanceof Date); // 输出: true
console.log(obj instanceof Object); // 输出: true
  • 局限性instanceof 只能用于判断对象是否是某个构造函数的实例,对于基本数据类型无法使用;而且如果对象跨 iframe 传递,由于不同 iframe 有不同的全局对象,instanceof 判断可能会不准确。

3. Object.prototype.toString.call() 方法

  • 原理:调用 Object.prototype.toString 方法并通过 call 方法将其应用到要判断的变量上,该方法会返回一个包含具体数据类型信息的字符串。
  • 适用场景:可以准确判断各种数据类型,包括基本数据类型和引用数据类型。
  • 代码示例
let num = 10;
let str = 'hello';
let bool = true;
let undef;
let nul = null;
let arr = [1, 2, 3];
let date = new Date();
let func = function() {};

console.log(Object.prototype.toString.call(num)); // 输出: "[object Number]"
console.log(Object.prototype.toString.call(str)); // 输出: "[object String]"
console.log(Object.prototype.toString.call(bool)); // 输出: "[object Boolean]"
console.log(Object.prototype.toString.call(undef)); // 输出: "[object Undefined]"
console.log(Object.prototype.toString.call(nul)); // 输出: "[object Null]"
console.log(Object.prototype.toString.call(arr)); // 输出: "[object Array]"
console.log(Object.prototype.toString.call(date)); // 输出: "[object Date]"
console.log(Object.prototype.toString.call(func)); // 输出: "[object Function]"
  • 缺点:返回的结果是一个字符串,需要进一步处理才能获取具体的类型名称;代码相对复杂一些。

4. Array.isArray() 方法

  • 原理:专门用于判断一个值是否为数组。
  • 适用场景:当需要明确判断一个变量是否为数组时使用。
  • 代码示例
let arr = [1, 2, 3];
let obj = {};

console.log(Array.isArray(arr)); // 输出: true
console.log(Array.isArray(obj)); // 输出: false

5. Number.isNaN()isNaN()

  • 原理
    • isNaN() 函数会先尝试将参数转换为数字,然后判断转换后的结果是否为 NaN
    • Number.isNaN() 只判断参数本身是否严格等于 NaN
  • 适用场景:用于判断一个值是否为 NaN
  • 代码示例
let nanValue = NaN;
let strValue = 'abc';

console.log(isNaN(nanValue)); // 输出: true
console.log(isNaN(strValue)); // 输出: true,因为 'abc' 转换为数字是 NaN

console.log(Number.isNaN(nanValue)); // 输出: true
console.log(Number.isNaN(strValue)); // 输出: false,因为 'abc' 本身不是 NaN

除了上述方法,还有其他方式判断数据类型吗?

1. 使用 constructor 属性

  • 原理:在 JavaScript 中,每个对象都有一个 constructor 属性,它指向创建该对象的构造函数。通过检查这个属性,我们可以判断对象的数据类型。
  • 适用场景:对于自定义对象和一些内置对象的判断较为方便,但对于基本数据类型的包装对象和跨 iframe 情况可能存在问题。
  • 代码示例
let num = 10;
let str = 'hello';
let arr = [1, 2, 3];
let obj = {};

console.log(num.constructor === Number); // 输出: true
console.log(str.constructor === String); // 输出: true
console.log(arr.constructor === Array); // 输出: true
console.log(obj.constructor === Object); // 输出: true
  • 局限性constructor 属性可以被修改,一旦被修改,判断结果就会不准确;对于基本数据类型,直接使用 constructor 可能会有意外结果,因为基本数据类型本身没有 constructor 属性,只有它们的包装对象才有。另外,在跨 iframe 环境下,不同 iframe 的构造函数是不同的,会导致判断失误。

2. 自定义类型检查函数

  • 原理:结合前面提到的方法,封装一个更通用、更具针对性的类型检查函数,根据不同的需求进行类型判断。
  • 适用场景:当需要在项目中多次进行类型判断,且希望代码更简洁、更易于维护时使用。
  • 代码示例
function getType(value) {
    const type = typeof value;
    if (type!== 'object') {
        return type;
    }
    return Object.prototype.toString.call(value).slice(8, -1).toLowerCase();
}

let num = 10;
let str = 'hello';
let arr = [1, 2, 3];
let date = new Date();
let func = function() {};

console.log(getType(num)); // 输出: "number"
console.log(getType(str)); // 输出: "string"
console.log(getType(arr)); // 输出: "array"
console.log(getType(date)); // 输出: "date"
console.log(getType(func)); // 输出: "function"
  • 优点:可以根据具体需求灵活调整判断逻辑,代码复用性高,能提高开发效率。

3. 使用 ReflectSymbol.toStringTag

  • 原理Symbol.toStringTag 是一个内置的 Symbol 值,对象可以通过定义这个属性来自定义 Object.prototype.toString.call() 的返回值。而 Reflect 是一个内置对象,它提供了拦截 JavaScript 操作的方法。
  • 适用场景:对于一些需要自定义类型标识的对象,或者想要更深入地控制类型判断结果的情况。
  • 代码示例
class MyCustomType {
    get [Symbol.toStringTag]() {
        return 'MyCustomType';
    }
}

let myObj = new MyCustomType();
console.log(Object.prototype.toString.call(myObj)); // 输出: "[object MyCustomType]"
  • 作用:可以让对象拥有自定义的类型标识,方便在类型判断时进行区分。

4. 使用第三方库(如 Lodash)

  • 原理:Lodash 是一个非常流行的 JavaScript 实用工具库,它提供了许多用于数据类型判断的函数,这些函数经过了严格的测试和优化,具有较高的准确性和稳定性。
  • 适用场景:在大型项目中,当需要进行复杂的类型判断,或者希望减少自己编写类型判断代码的工作量时使用。
  • 代码示例
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <script src="https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js"></script>
</head>

<body>
    <script>
        let arr = [1, 2, 3];
        let date = new Date();
        console.log(_.isArray(arr)); // 输出: true
        console.log(_.isDate(date)); // 输出: true
    </script>
</body>

</html>
  • 优点:使用方便,函数功能强大且兼容性好,能减少开发者的工作量。但引入第三方库会增加项目的体积,需要根据实际情况权衡。

http://www.kler.cn/a/554366.html

相关文章:

  • 【算法题】1749. 任意子数组和的绝对值的最大值(LeetCode)
  • XML XML约束 一、XML约束概述
  • 【HeadFirst系列之HeadFirst设计模式】第7天之命令模式:封装请求,轻松实现解耦!
  • 【python】python文件=注释=书写建议,基于pycharm
  • 媒体发稿价格标准是怎样?长期推广怎样控制好成本?
  • langchain系列 - FewShotPromptTemplate 少量示例
  • Linux阿里云服务器安装RocketMQ教程
  • 基于Flask框架的食谱数据可视化分析系统的设计与实现
  • linux 驱动编程配置(minis3c2440)
  • Springboot + Ollama + IDEA + DeepSeek 搭建本地deepseek简单调用示例
  • QT多线程编程基础
  • Android 11.0 WiFi连接默认设置静态IP地址功能实现
  • 跟李沐学AI:InstructGPT论文精读(SFT、RLHF)
  • 如何在Java爬虫中设置动态延迟以避免API限制
  • 缓存-算法
  • 6. 【.NET 8 实战--孢子记账--从单体到微服务--转向微服务】--微服务基础工具与技术--Ocelot 网关--概念与简单入门
  • uniapp多端适配
  • 【数据分享】2000—2024年逐月归一化植被指数(NDVI)栅格数据(免费获取/全国/分省)
  • 【JavaEE进阶】数据库连接池
  • web网络安全:跨站脚本攻击(XSS)