# 数据类型的获取

# typeof

typeof操作符返回一个字符串,表示未经计算的操作数的类型。

js 在底层存储变量时,会在变量的机器码的低位 1-3 位存储其类型信息。

  • 000 对象
  • 010 浮点数

诸如此类,其中nullundefined比较特殊,由于null代表的是空指针(大多数平台 下值为 0x00),所以

typeof null // 'object'
1

typeof null结果为object,但null并不是一个对象:

null instanceof null // TypeError: Right-hand side of 'instanceof' is not an object
1

所以一般只用typeof来判断基本数据类型。也可以使 用Object.prototype.toString.call(object)来判断。

# Object.prototype.toString.call

该方式是通过Object原型上的toString方法来获取对应的Tag,为何不直接通过本身 的toString方法呢?

let num = 1
num.toString() // '1' //基本类型本身没有toString方法,通过短暂的包装类即Number来操作

var name = 'homobulla'
str.toString() // 'homobulla'

obj.toString() // '[object Object]'
1
2
3
4
5
6
7

上面结果表明,所有类在继承 Object 的时候,都改写了 toString()方法。原 始Object上的toString方法可以输出数据的类型。而原始对象上的toString()方法, 转为对象后,会取得该对象的 [Symbol.toStringTag] 属性值(可能会遍历原型链)作为 tag,如无该属性,或该属性值不为字符串类型,则依下表取得 tag, 然后返回 "[object -" tag + "]" 形式的字符串。

// Boolean 类型,tag 为 "Boolean"
Object.prototype.toString.call(true) // => "[object Boolean]"

// Number 类型,tag 为 "Number"
Object.prototype.toString.call(1) // => "[object Boolean]"

// String 类型,tag 为 "String"
Object.prototype.toString.call('') // => "[object String]"

// Array 类型,tag 为 "String"
Object.prototype.toString.call([]) // => "[object Array]"

// Arguments 类型,tag 为 "Arguments"
Object.prototype.toString.call(
    (function () {
        return arguments
    })()
) // => "[object Arguments]"

// Function 类型, tag 为 "Function"
Object.prototype.toString.call(function () {}) // => "[object Function]"

// Error 类型(包含子类型),tag 为 "Error"
Object.prototype.toString.call(new Error()) // => "[object Error]"

// RegExp 类型,tag 为 "RegExp"
Object.prototype.toString.call(/\d+/) // => "[object RegExp]"

// Date 类型,tag 为 "Date"
Object.prototype.toString.call(new Date()) // => "[object Date]"

// 其他类型,tag 为 "Object"
Object.prototype.toString.call(new (class {})()) // => "[object Object]"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

# instanceof 操作符

instanceof运算符用于检测构造函数的prototype属性是否出现在某个实例对象的原型 链上。

instanceof原理:instanceof主要的实现原理就是只要右边变量的prototype在左边 变量的原型链上即可。因此,instanceof在查找的过程中会遍历左边变量的原型链,直到 找到右边变量的prototype,如果查找失败,则会返回false,告诉我们左边变量并非是 右边变量的实例。

function new_instance_of(leftVaule, rightVaule) {
    let rightProto = rightVaule.prototype // 取右表达式的 prototype 值
    leftVaule = leftVaule.__proto__ // 取左表达式的__proto__值
    while (true) {
        if (leftVaule === null) {
            return false
        }
        if (leftVaule === rightProto) {
            return true
        }
        leftVaule = leftVaule.__proto__
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13