JavaScript 数据类型
基本数据类型
运算符类型
解释每种基本数据类型
对象数据类型
结论
本文将解释每种 JavaScript 数据类型。我将重点介绍每种数据类型的简单定义,以及它们的一些特性和常见问题。
基本数据类型
原始数据类型是不可变的数据,它既没有属性也没有方法。
共有7种基本类型:
undefined,,,,,null(stringES5 number)boolean,symbol(bigintES11)
在解释每种类型之前,我想先介绍一下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 位来存储数字。因此,我们在处理数字时需要考虑以下两种情况:
- 安全整数
- 十进制数之间的运算
安全整数
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。
布尔值
它是一种表示两个布尔值的数据类型:true或false。
const isValid = true;
const isFetching = false;
const isLoading = Boolean(true);
typeof(isValid); // 'boolean'
typeof(isFetching); // 'boolean'
typeof(isLoading); // 'boolean'
您可以像前面的示例一样创建布尔值,也可以使用以下方式创建布尔值:
- 比较运算符和逻辑运算符
- 真值和假值。
比较运算符和逻辑运算符
比较运算符和逻辑运算符用于测试任何值数据类型并返回true或false。
比较运算符:
- 等值:
== - 等值且类型相同:
=== - 值不相等:
!= - 值不相等,类型也不相等:
!== - 大于:
> - 少于:
< - 大于或等于:
>= - 小于或等于:
<=
例如:
'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
符号用于:
- 识别物体的独特属性和隐藏属性。
- 找出唯一常量值列表。
- 实现常用符号以改变语言的某些特性: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