发布于 2026-01-06 6 阅读
0

JavaScript 数据类型 基本数据类型 typeof 运算符 解释每种基本数据类型 对象数据类型 结论

JavaScript 数据类型

基本数据类型

运算符类型

解释每种基本数据类型

对象数据类型

结论

本文将解释每种 JavaScript 数据类型。我将重点介绍每种数据类型的简单定义,以及它们的一些特性和常见问题。

基本数据类型

原始数据类型是不可变的数据,它既没有属性也没有方法。

共有7种基本类型:

undefined,,,,,nullstringES5 numberbooleansymbolbigintES11)

在解释每种类型之前,我想先介绍一下typeof运算符。

运算符类型

要了解任何值的类型,可以使用typeof运算符。typeof 运算符返回一个字符串,该字符串指示参数值的类型。

typeof("Hola") // string
typeof(12) // integer
typeof(true) // boolean
typeof(undefined) // undefined
typeof(null) // object
typeof({}) // object
typeof(Symbol()) // symbol
typeof(1n) // bigint
typeof(function(){}) // function

在前面的例子中,有两种情况下 typeof 运算符没有返回预期的数据类型:

  • typeof(null) = 'object'

  • typeof(function(){}) = 'function'

稍后我会解释这种行为的原因。

解释每种基本数据类型

不明确的

它是一种表示未定义值的数据类型。这意味着你声明了一个变量,但没有为其赋值。该变量将包含一个undefined值。

typeof 运算符对未定义的值或未声明的变量返回“undefined”。

var a;
console.log(a); // undefined
console.log(typeof(a)) // 'undefined'
console.log(typeof(b)) // 'undefined'
console.log(b) // Uncaught ReferenceError: b is not defined

如果你想清理一个变量,你可以设置它undefined,但这并不是一个好的做法。为此,你应该使用数据类型null

无效的

它是一种表示无值的数据类型。这意味着变量不包含任何值,或者你还不知道它的值。

当您想要表示变量已定义但没有值时,应该使用 `set`null而不是 ` is`。undefined

const a = null;
console.log(a); // null
console.log(typeof(a)); // 'object'

有趣的null是……typeof(null) = 'object'

这是一个意料之外的行为,因为 `null`null是一个原始数据类型,所以 `typeof(null)` 的结果应该是 `null` null。这是该语言从一开始就存在的一个 bug。之前曾有人提出过修复此 bug 的提案,但由于该修复会破坏大量已部署的代码而被否决。以下是该提案的链接:https://web.archive.org/web/20160331031419/http ://wiki.ecmascript.org:80/doku.php?id=harmony:typeof_null

细绳

它是一种表示文本的数据类型,用于存储和处理文本。

您可以string使用单引号、双引号或反引号来定义字符串。使用反引号,您可以在字符串内部连接和插入变量。

const name = 'Julian'; // Single quotation marks
const lastname = "Scialabba"; // Double quotation marks
const hello = `Hello ${name} ${lastname}`; // Backsticks -> Hello Julian Scialabba
console.log(typeof(hello)); // 'string'

字符串是一种原始数据类型。这意味着字符串没有方法。但是,为什么我们能做到这样的事情呢?

const name = 'Julian';
name.length // 6 
name.toUpperCase(); // JULIAN  
//Why this string primitive has attributes and methods?

你可以看到,我们的字符串基本类型表现得像一个对象,因为它有属性和方法。而这实际上正是因为它本身就是一个对象。JavaScript 内部会创建一个包装对象,为我们的字符串基本类型提供相应的功能。JavaScript 为除 `int` 和null`int`之外的所有基本数据类型都提供了包装对象undefined。因此, `int`null和 ` undefinedint` 没有方法,我们通常会遇到类似这样的错误:

var a;
var b = null;
var c = 'Hello';
console.log(a.toString()); // TypeError: a is undefined
console.log(b.toString()); // TypeError: b is null
console.log(c.toString()); // Hello

您也可以自行创建包装对象:

const name = String('Julian');
console.log(typeof(name)); // 'string'

这种创建字符串的方法很有用,因为它允许我们转换值。例如:

const numberStr = String(123);
const boolStr = String(true);
console.log(numberStr) // '123'
console.log(boolStr) // 'true'

您还可以使用“new”运算符创建包装对象:

const name = new String('Julian');
console.log(typeof(name)); // 'object'

但是,不建议使用这种创建原始值的方式。这种方式效率低下,而且可能会造成混淆,因为变量的类型是“对象”而不是“字符串”。

你也可以通过 JavaScript 类型强制转换来创建字符串。例如:

const age = 29;
const ageFromWrapperInteger = age.toString() // '29'
const ageCoercionStr = 29 + ''; // '29'
const isMaleCoercionStr = true + ''; // 'true'
console.log(typeof(ageFromWrapperInteger)); // 'string'
console.log(typeof(ageCoercionStr)); // 'string'
console.log(typeof(isMaleCoercionStr)); // 'string'

数字

它是一种表示带小数或不带小数的数字的数据类型。它用于存储和运算数字。

你可以number使用不带引号的数字或使用数字包装对象来定义一个值。

const number = 29;
const numberWithDecimals = 3.14;
const numberObjectWrapper = Number('2'); // 2
typeof(number); // 'number'
typeof(numberWithDecimals); // number
typeof(numberObjectWrapper); // number

JavaScript 中的数字采用双精度浮点数编码,遵循国际 IEEE 754 标准。这种格式使用 64 位来存储数字。因此,我们在处理数字时需要考虑以下两种情况:

  1. 安全整数
  2. 十进制数之间的运算

安全整数

JavaScript 中的数字有一个安全范围,在这个范围内你可以进行精确操作:

[Number.MIN_SAFE_INTEGER, Number.MAX_SAFE_INTEGER] = [-2**53+1, 2**53-1] = [-9007199254740991, 9007199254740991]

如果超出限制范围进行操作,操作精度会降低,某些数值可能无法表示。例如:

const maxSafe = Number.MAX_SAFE_INTEGER; //9007199254740991
const x = maxSafe + 1;  //9007199254740992
const y = maxSafe + 2;  //9007199254740992
x === y // true

ES11规范新增了一种基本数据类型,用于处理大于1的数字2**53 - 1。它叫做BigInt,稍后我会详细解释。

十进制数之间的运算

JavaScript 中的数字以二进制(基数为 2)系统存储。有些十进制小数无法精确地用二进制小数表示。因此,我们会遇到如下问题:

0.2 + 0.1 // 0.30000000000000004
0.2 - 0.3 // -0.09999999999999998

在进行分数运算以及需要精确计算时,务必谨慎。为了解决这个问题,我们有以下几种方法:

与图书馆合作:

如果需要精确度,可以使用像Big Decimal这样的库来处理这个问题。

整数:

你可以用这种方法对数字进行四舍五入。Number.toFixed(digits)

const number = 0.1 + 0.2; //// 0.30000000000000004
const numberFixedStr = number.toFixed(2); // '0.30'
const numberFixed = +number.toFixed(2); // 0.3

你可以看到它toFixed返回的是一个字符串。如果你想要得到一个整数,你需要+在结果的开头加上一个 `\n`(它会将字符串类型强制转换为数字类型)。

使用整数:

另一种方法是将所有十进制数转换为整数。然后对整数进行运算,最后返回原来的十进制数。例如:

const number1 = 0.1 * 100;
const number2 = 0.2 * 100;
(number1 + number2) / 100; // 0.3

NaN:非数字

NaN值是一个表示无效数字的数字。有一个方法isNaN(value)可以指示一个值是否为无效数字NaN

const x = 0/0; // NaN
const y = 1 * undefined; // NaN
const z = Number('Sarasa'); // NaN
typeof(x); // 'number'
typeof(y); // 'number'
typeof(z); // 'number'
x === y; // false
NaN === NaN // false
isNaN(x); // true

该值NaN不等于任何值,甚至不等于NaN

布尔值

它是一种表示两个布尔值的数据类型:truefalse

const isValid = true;
const isFetching = false;
const isLoading = Boolean(true);
typeof(isValid); // 'boolean'
typeof(isFetching); // 'boolean'
typeof(isLoading); // 'boolean'

您可以像前面的示例一样创建布尔值,也可以使用以下方式创建布尔值:

  • 比较运算符和逻辑运算符
  • 真值和假值。

比较运算符和逻辑运算符

比较运算符和逻辑运算符用于测试任何值数据类型并返回truefalse

比较运算符:
  • 等值:==
  • 等值且类型相同:===
  • 值不相等:!=
  • 值不相等,类型也不相等:!==
  • 大于:>
  • 少于:<
  • 大于或等于:>=
  • 小于或等于:<=

例如:

'123' == 123; // true
'123' === 123; // false
'123' != 123; // false
'123' !== 123; // true
123 > 123; // false
123 >= 123 // true
123 < 100 // false
123 <= 122 // true
逻辑运算符
  • 不是:!
  • 和:&&
  • 或者:||

例如:

!true // false
true && false // false
true || false // true
true && !false // true

比较运算符和逻辑运算符可以用于条件语句中:

const isValid = true;
const isFetching = false;
const name = '';
if(isValid && !isFetching){
 console.log('Fetch values');
}
if(!name) {
 console.log('User without name');
}

在第一个例子中,if你可以看到条件基于两个布尔值。然而,在第二个例子中,if条件是一个字符串值。为什么我们可以在条件语句中使用任何数据类型呢?这是因为 JavaScript 的类型强制转换以及真值和假值的存在。

虚假与真实的价值

JavaScript 类型强制转换是指将值从一种数据类型隐式转换为另一种数据类型。这种转换由 JavaScript 引擎自动完成。以下是一些示例:

'1' + 1 // '11' -> Converts Number to String and concat strings
'1' - 1 // 0 -> Converts String to Number and substract numbers
'1' * 1 // 1 -> Converts String to Number and multiply numbers
'1' + true // '1true' -> Converts Boolean to String and concat strings
1 + true // 2 -> Converts Boolean to Number and sum numbers. True = 1
1 + false // 1 -> Converts Boolean to Number and sum numbers. False = 0
'1' - true // 0 -> Converts String and Boolean to Numbers and substract numbers 

如果一个值位于条件语句中,它将被强制转换为布尔类型。被强制转换为布尔类型的值true称为“真值”,被强制转换为假值的值false称为“假值”。
所有非假值都是真值。因此,我们只需要知道假值即可:

  • 零号:0
  • BigInt 零:0n
  • 空字符串:''
  • 无效的:null
  • 不明确的:undefined
  • 不是数字:NaN
Boolean(0) // false
Boolean(0n) // false
Boolean('') // false
Boolean(null) // false
Boolean(undefined) // false
Boolean(NaN) // false
Boolean({}) // true -> Empty object is truthy
Boolean([]) // true -> Empty array is truthy
Boolean('Hello') // true

象征

它是 ES5 中引入的一种数据类型,用于表示唯一标识符。可以使用Symbol()带有可选字符串参数的方法来创建它。

const aSymbol = Symbol();
const symbolId = Symbol('id');
const anotherSymbolId = Symbpl('id');
typeof(aSymbol) // 'symbol'
symbolId === anotherSymbolId // false

每个符号都必须是唯一的。因此,描述相同的两个符号之间的等效比较是false。每次创建符号时Symbol(),您都会得到一个全新的、独一无二的符号,它与其他符号都不同。

Symbol() === Symbol() // false

符号用于:

  1. 识别物体的独特属性和隐藏属性。
  2. 找出唯一常量值列表。
  3. 实现常用符号以改变语言的某些特性:https://tc39.es/ecma262/#table-1

BigInt

BigInt 是 ES11 中引入的一种数据类型。它表示大于 100 的数字2**53 - 1,而 100 是基本数据类型 number 的整数长度限制。BigInt 支持任意长度的整数,但不支持十进制值。

n可以通过在数字末尾添加逗号或使用包装对象来创建 BigInt 类型。BigInt(value)

const bigIntValue = BigInt(1); // 1n
const anotherBigIntValue = BigInt('9999') // 9999n
bigIntValue + anotherBigIntValue // 10000n
const maxSafeInteger = 9007199254740991n; // MAX_SAFE_INTEGER
const maxSafeInteger1 = maxSafeInteger + 1n; // 9007199254740992n
const maxSafeInteger2 = maxSafeInteger + 2n; // 9007199254740993n -> With numbers we can't get this value
maxSafeInteger1 !== maxSafeInteger2 // true
typeof(maxSafeInteger) // 'bigint'

BigInt 可用的运算符有:+, *, -, **, /, %。您不能使用这些运算符对 BigInt 和 Number 进行运算。您也不能使用该Math库,因为该库使用的是 Number 数据类型。

const maxSafeInteger = 9007199254740991n;
maxSafeInteger + 9n // 9007199254741000n
maxSafeInteger - 1n // 9007199254740990n
maxSafeInteger * 2n // 18014398509481982n
maxSafeInteger ** 2n // 81129638414606663681390495662081n
5n / 2n // 2n -> It is rounded towards 0 because BigInt doesn't represent decimals
maxSafeInteger % 2n // 1n
maxSafeInteger + 2 // can't convert BigInt to number
Math.pow(3n,2) // can't convert BigInt to number

BigInt 和 Number 之间的比较没有问题:

3n > 2 // true
1n > 2 // false
2n >= 2 // true
2n == 2 // true
2n === 2 // false -> The types are different

最后,BigInt 的唯一假值是0n

Boolean(0n) // false
Boolean(1n) // true

不建议将 BigInt 强制转换为 Number。如果需要小于 100 的数字2**53 -1,应使用 Number 数据类型。如果需要大于 100 的数字2**53 -1,应使用 BigInt 数据类型。

如果将大于某个值的 BigInt 强制转换2**53 -1为数字,可能会损失精度。

Number(1n) //1
Number(9007199254740993n) //9007199254740992

对象数据类型

在 JavaScript 中,所有非原始数据类型的值都是对象数据类型。

对象数据类型用于表示具有属性和方法的值。原始数据类型表示简单的不可变值,而对象数据类型则表示数据集合和更复杂的实体。

典型的 JavaScript 键值结构是一种对象数据类型。

const person = {
  name: 'Julian',
  lastname: 'Scialabba'
};
typeof(person); // 'object'

数组、函数、集​​合、哈希映射、日期等其他结构也是对象数据类型。

const numbers = [1, 2, 3, 4];
const aSet = new Set();
const aDate = new Date();
const sayHello = function(name){
  console.log(`Hello ${name}!`);
}
typeof(numbers) // 'object'
typeof(aSet) // 'object'
typeof(aDate) // 'object'
typeof(sayHello) // 'function'

我们可能预期会这样,typeof(function(){}) = 'object'但实际情况并非如此typeof(function(){}) = 'function'。这可以解释为 ECMAScript 规范对 typeof 运算符的定义如下:

值类型 结果
不明确的 '不明确的'
无效的 '目的'
布尔值 '布尔值'
数字 '数字'
细绳 '细绳'
对象(未实现 [[Call]]) '目的'
对象(实现 [[Call]]) '功能'

所以,typeof(function(){}) = 'function'因为函数是一个实现了 [[Call]] 的对象。

结论

我已经解释了所有基本数据类型和对象数据类型。我重点介绍了每种数据类型的简单定义,以及它们的一些特性和常见问题。

希望您喜欢这篇文章!欢迎在评论区留言分享您的想法。

感谢阅读!

文章来源:https://dev.to/juliansci/javascript-data-types-112g