Skip to content

js中的数据类型

前言

说一下js的几种数据类型。

当这样问自己的时候,发现并不能很流利的回答出来,学了这么久的js,可真是太不扎实了,本篇文章就对这个问题做个梳理,简单的总结一下。

所有数据类型

记忆方法

我会这样去记忆:

  1. 基本类型

    undefined、null

    string number bigint

    boolean

    symbol

  2. 引用类型

    object、function

为什么按上面这样列呢?其实是按照typeof运算符的返回值记忆的。不过typeof null并不会返回null,而是会返回object,这个特殊记一下。另外还有一个NaN,它是not a number的缩写,虽然它不是数值,但是使用typeof NaN做运算时,仍会返回number,这个也需要特殊记忆一下。然后就是function,它实际上也是一个object

typeof 的使用 参考另一篇文章:typeof

undefined

什么时候会返回undefined呢?

  1. 访问声明,但未初始化的变量

    js
    let aaa
    console.log(aaa) // undefined
  2. 访问对象不存在的属性

    js
    let bbb = {}
    console.log(bbb.a); // undefined
  3. 访问没有被显示传值的函数参数

    js
    (function (a) {
        console.log(a); // undefined
    })()
  4. 访问任何被设置为undefined值的变量

    js
    let ccc = undefined
    console.log(ccc); // undefined
  5. 没有定义return的函数隐士返回undefined

    js
    function ddd() { }
    console.log(ddd()); // undefined
  6. 函数return没有显示的返回任何内容

    js
    function eee() {
        return
    }
    console.log(eee()); // undefined
  7. 数组未显示填充值的位置处,默认赋值为undefined

    js
    let 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中的字符串有下面两种定义方式

  1. 字符串字面量(单引号或双引号)

    js
    let str1 = "abc"
    let str2 = "456"
    let str1 = 'aaa'
  2. 使用String函数声明

    js
    // thing 表示任何可以被转换成字符串的值。
    // String(thing)
    // new String(thing)
  3. ES6中的模板字符串

    js
    let str = `abc`

基本字符串与字符换对象的区别。

字符串字面量 (通过单引号或双引号定义) 和 直接调用 String 方法(没有通过 new 生成字符串对象实例)的字符串都是基本字符串。JavaScript会自动将基本字符串转换为字符串对象,只有将基本字符串转化为字符串对象之后才可以使用字符串对象的方法。

js
let 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,所以也有下面几种定义方式

  1. 直接使用数字

  2. 使用Number构造器

    js
    let 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。

js
const bigint = 1234567890123456789012345678901234567890n;

const sameBigint = BigInt("1234567890123456789012345678901234567890");

const bigintFromNumber = BigInt(10); // 与 10n 相同

BigInt 大多数情况下可以像常规数字类型一样使用,例如:

js
console.log(1n + 2n); // 3n

console.log(5n / 2n); // 2n

请注意:除法 5/2 的结果向零进行舍入,舍入后得到的结果没有了小数部分。对 bigint 的所有操作,返回的结果也是 bigint。

我们不可以把 bigint 和常规数字类型混合使用:

js
console.log(1n + 2) // TypeError: Cannot mix BigInt and other types, use explicit conversions

如果有需要,我们应该显式地转换它们:使用 BigInt() 或者 Number(),像这样:

js
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 中不支持一元加法:

js
let bigint = 1n;

console.log(+bigint); // TypeError: Cannot convert a BigInt value to a number

所以我们应该用 Number() 来将一个 bigint 转换成一个数字类型。

比较运算符,例如 <>,使用它们来对 bigint 和 number 类型的数字进行比较没有问题:

js
console.log( 2n > 1n ); // true

console.log( 2n > 1 ); // true

但是请注意,由于 number 和 bigint 属于不同类型,它们可能在进行 == 比较时相等,但在进行 ===(严格相等)比较时不相等:

js
console.log( 1 == 1n ); // true

console.log( 1 === 1n ); // false

当在 if 或其他布尔运算中时,bigint 的行为类似于 number。

例如,在 if 中,bigint 0n 为假,其他值为 true

js
if (0n) {
  // 永远不会执行
}

布尔运算符,例如 ||&& 和其他运算符,处理 bigint 的方式也类似于 number:

js
console.log( 1n || 2 ); // 1n(1n 被认为是真)

console.log( 0n || 2 ); // 2(0n 被认为是假)

参考:https://zh.javascript.info/bigint

boolean

boolean 类型仅包含两个值:truefalse

这种类型通常用于存储表示 yes 或 no 的值:true 意味着 “yes,正确”,false 意味着 “no,不正确”。

比如:

js
let nameFieldChecked = true; // yes, name field is checked
let ageFieldChecked = false; // no, age field is not checked

布尔值也可作为比较的结果:

js
let isGreater = 4 > 1;

alert( isGreater ); // true(比较的结果是 "yes")

symbol

根据规范,对象的属性键只能是字符串类型或者 Symbol 类型。不是 Number,也不是 Boolean,只有字符串或 Symbol 这两种类型。

“Symbol” 值表示唯一的标识符。

可以使用 Symbol() 来创建这种类型的值:

js
// id 是 symbol 的一个实例化对象
let id = Symbol();

创建时,我们可以给 Symbol 一个描述(也称为 Symbol 名),这在代码调试时非常有用:

js
// id 是描述为 "id" 的 Symbol
let id = Symbol("id");

Symbol 保证是唯一的。即使我们创建了许多具有相同描述的 Symbol,它们的值也是不同。描述只是一个标签,不影响任何东西。

例如,这里有两个描述相同的 Symbol —— 它们不相等:

js
let id1 = Symbol("id");
let id2 = Symbol("id");

console.log(id1 === id2); // false

Symbol 不会被自动转换为字符串

JavaScript 中的大多数值都支持字符串的隐式转换。例如,我们可以 alert 任何值,都可以生效。Symbol 比较特殊,它不会被自动转换。

例如,这个 alert 将会提示出错:

js
let id = Symbol("id");
alert(id); // 类型错误:无法将 Symbol 值转换为字符串。

这是一种防止混乱的“语言保护”,因为字符串和 Symbol 有本质上的不同,不应该意外地将它们转换成另一个。

如果我们真的想显示一个 Symbol,我们需要在它上面调用 .toString(),如下所示:

js
let id = Symbol("id");
alert(id.toString()); // Symbol(id),现在它有效了

或者获取 symbol.description 属性,只显示描述(description):

js
let id = Symbol("id");
alert(id.description); // id

具体参考:https://zh.javascript.info/symbol

object

我们可以用下面两种语法中的任一种来创建一个空的对象

js
let user = new Object(); // “构造函数” 的语法
let user = {};  // “字面量” 的语法

对象的属性命名没有限制,可以是任何字符串或者 symbol,例如,当数字 0 被用作对象的属性的键时,会被转换为字符串 "0"

js
let obj = {
  0: "test" // 等同于 "0": "test"
};

参考:https://zh.javascript.info/object#shu-xing-ming-cheng-xian-zhi

function

两种声明方式

  1. 使用function关键字

    js
    function fn() { }
    console.log(typeof fn); // function
    
    let fn2 = function () { }
    console.log(typeof fn2); // function
  2. 使用new Function(),(不怎么使用)

    js
    let fn3 = new Function('a,b', 'return a+b')
    console.log(typeof fn3); // function

所有的function都可以使用new关键字声明出来一个实例对象。

function实际上也是一个对象,也能在上面添加属性,比如

js
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 用于 truefalse
  • null 用于未知的值 —— 只有一个 null 值的独立类型。
  • undefined 用于未定义的值 —— 只有一个 undefined 值的独立类型。
  • symbol 用于唯一的标识符。
  • object 用于更复杂的数据结构。
  • function 实际上也是一个object,可以使用new关键字声明实例对象

我们可以通过 typeof 运算符查看存储在变量中的数据类型。

  • 两种形式:typeof x 或者 typeof(x)
  • 以字符串的形式返回类型名称,例如 "string"
  • typeof null 会返回 "object" —— 这是 JavaScript 编程语言的一个错误,实际上它并不是一个 object

参考

https://zh.javascript.info/types#zong-jie