Javascript 类型判断

JavaScript 具有七种内置数据类型,它们分别是:

  • null
  • undefined
  • boolean
  • number
  • string
  • object
  • symbol

javascript判断数据类型的方法: typeofinstanceofconstructorobject.prototype.toString

typeof

typeof 判断基础数据类型:

1
2
3
4
5
6
7
8
typeof undefined // "undefined"
typeof true // "boolean"
typeof 'string' // "string"
var a
typeof a // 'undefined'
typeof b // 'undefined' // 即使b未声明,也会返回undefined
// 特殊
typeof null === 'object'

typeof 判断复杂数据类型:

1
2
3
4
5
typeof [] // "object"
typeof {} // "object"
typeof Symbol('foo') // "symbol"
typeof function a() {} // "function"
typeof new Date() // "object"

typeof 返回类型的字符串值, 使用 typeof 判断基本类型时,不能判断 null 类型,判断复杂类型时,可以判断出 function 类型、symbol类型。

结论

typeof 通常用来检测一个对象是否定义,不能判断 Object 类型

instanceof

左操作符是对象,右操作符是函数或构造器,判断:右边的构造器中 prototype 属性是否出现在左边的对象的原型链上

instanceof 的原理:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function instanceof(left, right) {
if (typeof left !== 'object') {
return false
}
let proto = left._proto_;
let prototype = right.prototype;
while(true) {
if(proto === prototype) {
return true
}
if(proto === null) {
return false
}
proto = proto._proto_
}
}

instanceof 作用

  • 检测一个对象是否是属于某种类型

    1
    2
    3
    function Foo(){}
    var foo = new Foo();
    console.log(foo instanceof Foo) //true
  • 在继承关系中判断一个实例是否是属于他的父类型。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    function Foo() {}
    function Bar() {}
    Bar.prototype = new Foo();
    var bar = new Bar();
    bar instanceof Bar; // true
    bar instanceof Foo; // true
    // 如果仅仅设置 Bar.prototype 为函数 Foo 本身,而不是 Foo 构造函数的一个实例
    Bar.prototype = Foo;
    new Bar() instanceof Foo; // false

instanceof 缺陷:

1
2
3
4
5
6
7
var str1 = 'hello';
console.log(str1 instanceof String); // false
var str2 = new String('jomsou');
console.log(str2 instanceof String); // true
var arr = [1, 2, 3];
arr instanceof Array; // true
arr instanceof Object; // true

结论

instanceof 不能判断基本类型,object 类型判断也有问题,但是可以准确的判断 Array 类型(instanceof 无法判断 iframe 的数组类型)

准确的判断数组的方法:

1
2
arr instanceof Array
Array.isArray() // Array.isArray() IE9以下的浏览器可能不兼容

constructor

使用 constructor 可以查看目标的构造函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var a = [];
a.constructor // ƒ Array() { [native code] }
a.constructor == Array; // true

var b = {};
b.constructor // ƒ Object() { [native code] }
b.constructor == Object; // true

var foo = Symbol("foo")
foo.constructor // ƒ Symbol() { [native code] }

// 特殊
var foo = undefined
foo.constructor // VM241:2 Uncaught TypeError: Cannot read property 'constructor' of undefined at <anonymous>:2:5

var foo = null
foo.constructor // VM247:2 Uncaught TypeError: Cannot read property 'constructor' of null at <anonymous>:2:5

constructor 对 undefinded 和 null, 如果尝试读取 constructor 属性,会报错。constructor 返回的是构造函数本身,一般不用来进行类型判断。

object.prototype.toString

对象内部属性[[class]]的值,需要通过Object.prototype.toString()获取。检测一个对象的类型,这是唯一一个可依赖的方法。

  • 判断基本数据类型:

    1
    2
    3
    4
    5
    Object.prototype.toString.call(null);//"[object Null]";
    Object.prototype.toString.call(undefined);//"[object undefined]";
    Object.prototype.toString.call("abc");//"[object String]";
    Object.prototype.toString.call(123);//"[object Number]";
    Object.prototype.toString.call(true);//"[object Boolean]";
  • 判断原生引用类型:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    //函数类型 
    function fn(){console.log("test");}
    Object.prototype.toString.call(fn);//"[object Function]";
    //日期类型
    var date = new Date();
    Object.prototype.toString.call(date);//"[object Date]";
    //数组类型
    var arr = [1,2,3];
    Object.prototype.toString.call(arr);//”[object Array]”
    //正则表达式
    var reg = /[hbc]at/gi;
    Object.prototype.toString.call(reg);//”[object RegExp]”
    //自定义类型
    function Person(name, age) {
    this.name = name;
    this.age = age;
    }
    var person = new Person("Rose", 18);
    Object.prototype.toString.call(arr); //”[object Object]”