js中的数据类型
前言
说一下js的几种数据类型。
当这样问自己的时候,发现并不能很流利的回答出来,学了这么久的js,可真是太不扎实了,本篇文章就对这个问题做个梳理,简单的总结一下。
所有数据类型
记忆方法
我会这样去记忆:
基本类型
undefined、null
string number bigint
boolean
symbol
引用类型
object、function
为什么按上面这样列呢?其实是按照
typeof
运算符的返回值记忆的。不过typeof null
并不会返回null
,而是会返回object
,这个特殊记一下。另外还有一个NaN
,它是not a number
的缩写,虽然它不是数值,但是使用typeof NaN
做运算时,仍会返回number
,这个也需要特殊记忆一下。然后就是function
,它实际上也是一个object
typeof
的使用 参考另一篇文章:typeof
undefined
什么时候会返回undefined
呢?
访问声明,但未初始化的变量
jslet aaa console.log(aaa) // undefined
访问对象不存在的属性
jslet bbb = {} console.log(bbb.a); // undefined
访问没有被显示传值的函数参数
js(function (a) { console.log(a); // undefined })()
访问任何被设置为
undefined
值的变量jslet ccc = undefined console.log(ccc); // undefined
没有定义
return
的函数隐士返回undefined
jsfunction ddd() { } console.log(ddd()); // undefined
函数
return
没有显示的返回任何内容jsfunction eee() { return } console.log(eee()); // undefined
数组未显示填充值的位置处,默认赋值为
undefined
jslet arr = [1, , 3] console.log(arr[1]); // undefined
null
当某个对象不需要了的时候,我们可以显示的给其赋值为null
,释放内存空间。
undefined和null的区别
null
表示“没有对象”,该处不应该有值。undefined
表示“缺少值”,就是此处应该有一个值,但是还没有定义。参考:http://www.ruanyifeng.com/blog/2014/03/undefined-vs-null.html
string
js中的字符串有下面两种定义方式
字符串字面量(单引号或双引号)
jslet str1 = "abc" let str2 = "456" let str1 = 'aaa'
使用
String
函数声明js// thing 表示任何可以被转换成字符串的值。 // String(thing) // new String(thing)
ES6中的模板字符串
jslet str = `abc`
基本字符串与字符换对象的区别。
字符串字面量 (通过单引号或双引号定义) 和 直接调用 String 方法(没有通过 new 生成字符串对象实例)的字符串都是基本字符串。JavaScript会自动将基本字符串转换为字符串对象,只有将基本字符串转化为字符串对象之后才可以使用字符串对象的方法。
jslet str1 = '123' let str2 = String(456) let str3 = new String('aaa') console.log(typeof str1); // string console.log(typeof str2); // string console.log(typeof str3); // object
当基本字符串需要调用一个字符串对象才有的方法或者查询值的时候(基本字符串是没有这些方法的),JavaScript 会自动将基本字符串转化为字符串对象并且调用相应的方法或者执行查询。
参考:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/String
number
类型number
与类型string
类似,number
也有一个包装类Number
,所以也有下面几种定义方式
直接使用数字
使用
Number
构造器jslet a = 123 let b = 1.123 let c = Number(123) let d = new Number(123) console.log(typeof a); // number console.log(typeof b); // number console.log(typeof c); // number console.log(typeof d); // object
直接使用数字或者
String(number)
声明出来的都是一样的效果,使用new Number()
声明出来的是对象。当想使用
Number
原型上的方法时,会将数字自动的转换为Number
的包装对象。使用
Number(xxx)
,如果传入的参数无法转为为数字,会返回NaN
。
js的整数取值范围是(-2^53, 2^53)
(不包含两个端点),在解析序列化的JSON时,如果JSON解析器将它们强制转换为Number类型,那么超出此范围的整数值可能会被破坏。
参考:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Number
bigint
BigInt
是一种特殊的数字类型,它提供了对任意长度整数的支持。
创建 bigint 的方式有两种:在一个整数字面量后面加 n
或者调用 BigInt
函数,该函数从字符串、数字等中生成 bigint。
const bigint = 1234567890123456789012345678901234567890n;
const sameBigint = BigInt("1234567890123456789012345678901234567890");
const bigintFromNumber = BigInt(10); // 与 10n 相同
BigInt
大多数情况下可以像常规数字类型一样使用,例如:
console.log(1n + 2n); // 3n
console.log(5n / 2n); // 2n
请注意:除法 5/2
的结果向零进行舍入,舍入后得到的结果没有了小数部分。对 bigint 的所有操作,返回的结果也是 bigint。
我们不可以把 bigint 和常规数字类型混合使用:
console.log(1n + 2) // TypeError: Cannot mix BigInt and other types, use explicit conversions
如果有需要,我们应该显式地转换它们:使用 BigInt()
或者 Number()
,像这样:
let bigint = 1n;
let number = 2;
// 将 number 转换为 bigint
console.log(bigint + BigInt(number)); // 3n
// 将 bigint 转换为 number
console.log(Number(bigint) + number); // 3
转换操作始终是静默的,绝不会报错,但是如果 bigint 太大而数字类型无法容纳,则会截断多余的位,因此我们应该谨慎进行此类转换。
BigInt 不支持一元加法
一元加法运算符
+value
,是大家熟知的将value
转换成数字类型的方法。为了避免混淆,在 bigint 中不支持一元加法:
jslet bigint = 1n; console.log(+bigint); // TypeError: Cannot convert a BigInt value to a number
所以我们应该用
Number()
来将一个 bigint 转换成一个数字类型。
比较运算符,例如 <
和 >
,使用它们来对 bigint 和 number 类型的数字进行比较没有问题:
console.log( 2n > 1n ); // true
console.log( 2n > 1 ); // true
但是请注意,由于 number 和 bigint 属于不同类型,它们可能在进行 ==
比较时相等,但在进行 ===
(严格相等)比较时不相等:
console.log( 1 == 1n ); // true
console.log( 1 === 1n ); // false
当在 if
或其他布尔运算中时,bigint 的行为类似于 number。
例如,在 if
中,bigint 0n
为假,其他值为 true
:
if (0n) {
// 永远不会执行
}
布尔运算符,例如 ||
,&&
和其他运算符,处理 bigint 的方式也类似于 number:
console.log( 1n || 2 ); // 1n(1n 被认为是真)
console.log( 0n || 2 ); // 2(0n 被认为是假)
参考:https://zh.javascript.info/bigint
boolean
boolean 类型仅包含两个值:true
和 false
。
这种类型通常用于存储表示 yes 或 no 的值:true
意味着 “yes,正确”,false
意味着 “no,不正确”。
比如:
let nameFieldChecked = true; // yes, name field is checked
let ageFieldChecked = false; // no, age field is not checked
布尔值也可作为比较的结果:
let isGreater = 4 > 1;
alert( isGreater ); // true(比较的结果是 "yes")
symbol
根据规范,对象的属性键只能是字符串类型或者 Symbol 类型。不是 Number,也不是 Boolean,只有字符串或 Symbol 这两种类型。
“Symbol” 值表示唯一的标识符。
可以使用 Symbol()
来创建这种类型的值:
// id 是 symbol 的一个实例化对象
let id = Symbol();
创建时,我们可以给 Symbol 一个描述(也称为 Symbol 名),这在代码调试时非常有用:
// id 是描述为 "id" 的 Symbol
let id = Symbol("id");
Symbol 保证是唯一的。即使我们创建了许多具有相同描述的 Symbol,它们的值也是不同。描述只是一个标签,不影响任何东西。
例如,这里有两个描述相同的 Symbol —— 它们不相等:
let id1 = Symbol("id");
let id2 = Symbol("id");
console.log(id1 === id2); // false
Symbol 不会被自动转换为字符串
JavaScript 中的大多数值都支持字符串的隐式转换。例如,我们可以
alert
任何值,都可以生效。Symbol 比较特殊,它不会被自动转换。例如,这个
alert
将会提示出错:jslet id = Symbol("id"); alert(id); // 类型错误:无法将 Symbol 值转换为字符串。
这是一种防止混乱的“语言保护”,因为字符串和 Symbol 有本质上的不同,不应该意外地将它们转换成另一个。
如果我们真的想显示一个 Symbol,我们需要在它上面调用
.toString()
,如下所示:jslet id = Symbol("id"); alert(id.toString()); // Symbol(id),现在它有效了
或者获取
symbol.description
属性,只显示描述(description):jslet id = Symbol("id"); alert(id.description); // id
具体参考:https://zh.javascript.info/symbol
object
我们可以用下面两种语法中的任一种来创建一个空的对象
let user = new Object(); // “构造函数” 的语法
let user = {}; // “字面量” 的语法
对象的属性命名没有限制,可以是任何字符串或者 symbol,例如,当数字 0
被用作对象的属性的键时,会被转换为字符串 "0"
:
let obj = {
0: "test" // 等同于 "0": "test"
};
参考:https://zh.javascript.info/object#shu-xing-ming-cheng-xian-zhi
function
两种声明方式
使用
function
关键字jsfunction fn() { } console.log(typeof fn); // function let fn2 = function () { } console.log(typeof fn2); // function
使用
new Function()
,(不怎么使用)jslet fn3 = new Function('a,b', 'return a+b') console.log(typeof fn3); // function
所有的function
都可以使用new
关键字声明出来一个实例对象。
function
实际上也是一个对象,也能在上面添加属性,比如
function fn() { }
fn.a = 'aaa'
console.log(fn.a) // aaa
具体参考:
http://www.bnbiye.cn/#/articleDetail/87ecdb40-4e5b-11ec-96d5-7933aca11ca0
https://zh.javascript.info/function-basics
总结
JavaScript 中有八种基本的数据类型(译注:前七种为基本数据类型,也称为原始类型,而 object
为复杂数据类型,还有一个function
,实际上也是object
)。
number
用于任何类型的数字:整数或浮点数,在±(253-1)
范围内的整数。bigint
用于任意长度的整数。string
用于字符串:一个字符串可以包含 0 个或多个字符,所以没有单独的单字符类型。boolean
用于true
和false
。null
用于未知的值 —— 只有一个null
值的独立类型。undefined
用于未定义的值 —— 只有一个undefined
值的独立类型。symbol
用于唯一的标识符。object
用于更复杂的数据结构。function
实际上也是一个object
,可以使用new
关键字声明实例对象
我们可以通过 typeof
运算符查看存储在变量中的数据类型。
- 两种形式:
typeof x
或者typeof(x)
。 - 以字符串的形式返回类型名称,例如
"string"
。 typeof null
会返回"object"
—— 这是 JavaScript 编程语言的一个错误,实际上它并不是一个object
。