重学JavaScript之数据类型

438 阅读2分钟

概念

js数据类型分为两大类总计8种,分别是:

  • 原始值
    • Undefined
    • Null
    • String
    • Number
    • Boolean
    • BigInt
    • Symbol
  • 对象
    • Object

其中Object类型还包含很多种,比如Function, Array, Date, Math, RegExp等

原始值也就是基础数据类型,存储在栈内存,被引用或被拷贝时,会创建一个完全相等的变量。 对象也就是引用类型,存储在堆内存,存储的是地址,多个引用指向一个地址。

对象类型的引用会有一个“共享”的特性,比如下面这段代码:

const a = {
    name: 'foo'
}
const b = a
console.log(a.name) //foo
b.name = 'bar'
console.log(b.name) //bar
console.log(a.name) //bar

变量a接收一个对象obj在堆内存的地址,传递给变量b,b也指向了obj的地址,所以操作b修改obj的值时,a同时更新了。

再看下面这段代码:

const a = {
   name: 'foo',
   age: 18
}

function change(o) {
    o.age = 24
    o = {
        name: 'bar',
        age: 30
    }
    return o
}

const b = change(a)
console.log(b.age) // 30
console.log(a.age) // 24

这里change函数返回了一个新的对象,所以a与b没有关联。

检测方法

知道了以上这些类型,那么该如何判断一个变量是哪种类型呢?

这里直接抛出3种常用方法:

1.typeof

typeof 1 // 'number'
typeof '1' // 'string'
typeof 1n // 'bigint'
typeof undefined // 'undefined'
typeof true // ''boolean'
typeof Symbol() // 'symbol'
typeof null // 'object'
typeof {} // 'object'
typeof [] // 'object'
typeof alert // 'function'

可以看出,typeof可以区分全部基础数据类型,不能区分数组和对象。typeof null比较特殊,这是一个历史遗留问题,暂不讨论,但请记住。

2.instanceof

const Car = function () {}
const byd = new Car()
byd instanceof Car // true

instanceof用于检测对象是否是某个构造函数的实例,但是这个并不能保证一定正确,比如修改byd的原型链:

const Car = function () {}
const byd = new Car()
byd.__proto__ = {}
byd instanceof Car // false

再比如修改Car的原型:

const Car = function () {}
const byd = new Car()
Car.prototype = {}
byd instanceof Car // false

故,在代码环。境靠谱的前提下,instanceof可用于检测自定义对象类型

3.Object.prototype.toString

每个对象都有一个toString()方法,当该对象被表示为一个文本值时,或者一个对象以预期的字符串方式引用时自动调用。默认情况下,toString() 方法被每个 Object 对象继承。如果此方法在自定义对象中未被覆盖,toString() 返回 "[object type]",其中 type 是对象的类型。以下代码说明了这一点:

var o = new Object();
o.toString(); // '[object Object]'

因此可以通过toString() 方法来获取每个对象的类型:

const toString = Object.prototype.toString
toString.call(1) // '[object Number]'
toString.call('1') //  '[object String]'
toString.call(null); // '[object Null]'
toString.call(undefined); // '[object Undefined]'
toString.call(Math); // '[object Math]'

可以看出Object.prototype.toString可以检测所有标准的数据类型,注意是标准的数据类型,自定义的对象检测结果都是'[object Object]'。

以上3种方法视场景使用或搭配使用。

代码练习:

const getType = (obj) => {
    return Object.prototype.toString.call(obj).replace(/^\[object (\S+)\]$/, '$1').toLowerCase()
}