# javascript中如何判断变量类型?
# typeof
判断基本类型,返回一个字符串
typeof 123 === 'number' // true
| 类型 | 结果 | 
|---|---|
| Undefined | "undefined" | 
| Null | "object"(见下文) | 
| Boolean | "boolean" | 
| Number | "number" | 
| String | "string" | 
| Symbol (ECMAScript 6 新增) | "symbol" | 
| 宿主对象(由JS环境提供) | Implementation-dependent | 
| 函数对象([[Call]] 在ECMA-262条款中实现了) | "function" | 
| 任何其他对象 | "object" | 
# instanceof
检查某个对象属于哪个构造函数
function A(){}
let a = new A()
a instanceof A // true
# 更详细的解释
由于具体实现上的问题,在实际的项目应用中,typeof只有两个用途,就是检测一个元素是否为undefined,或者是否为function。
# 为何呢?
JavaScript Garden整理出来了如下表格:
| Value | function | typeof | 
|---|---|---|
| "foo" | String | string | 
| new String("foo") | String | object | 
| 1.2 | Number | number | 
| new Number(1.2) | Number | object | 
| true | Boolean | boolean | 
| new Boolean(true) | Boolean | object | 
| new Date() | Date | object | 
| new Error() | Error | object | 
| [1,2,3] | Array | object | 
| new Array(1, 2, 3) | Array | object | 
| new Function("") | Function | function | 
| /abc/g | RegExp | object | 
| new RegExp("meow") | RegExp | object | 
| {} | Object | object | 
| new Object() | Object | object | 
所以我们一般用“鸭子类型”来做流程控制。
# 一定要区分这些东西?
Object.prototype.toString()有一个妙用,如果我们以某个特别的对象为上下文来调用该函数,它会返回正确的类型。我们需要做的就是手动处理其返回的字符串,最终便能获得typeof应该返回的正确字符串。
可以用来区分:Boolean, Number, String, Function, Array, Date, RegExp, Object, Error等等。
jQuery.type()就是这样实现的。以下代码从jQuery源码中抽取出来,可以直接用。
var class2type = {} ;
"Boolean Number String Function Array Date RegExp Object Error".split(" ").forEach(function(e,i){
    class2type[ "[object " + e + "]" ] = e.toLowerCase();
}) ;
//当然为了兼容IE低版本,forEach需要一个polyfill,不作细谈了。
function _typeof(obj){
    if ( obj == null ){
        return String( obj );
    }
    return typeof obj === "object" || typeof obj === "function" ?
        class2type[ class2type.toString.call(obj) ] || "object" :
        typeof obj;
}
使用结果:
_typeof(new String())
->"string"
_typeof("123")
->"string"
_typeof(new RegExp())
->"regexp"
_typeof(null)
->"null"
# 公认的方法
即使都是object类型,也还是有区分的。比如[object Object] [object String]...
Object.prototype.toString.call(x) === '[object Array]'
# 鸭子类型
- js是一门动态语言,指的是在运行过程中可以改变其结构等。
比如var a=0 a='3'+5
- 鸭子类型是动态类型的一种风格。在这种风格中,一个对象有效的语义,不是由继承自特定的类或实现特定的接口,而是由“当前方法和属性的集合”决定。
- 当看到一只鸟走起来像鸭子,游泳像鸭子,叫起来像鸭子,那么这只鸟就可以被称之为鸭子。
- 在鸭子类型中,关注点在于对象的行为,能做什么,而不是关注类型。
- 可以理解为,在不继承的情况下使用了多态。
// 应聘选手鸭子
let duck = {
    voice: '嘎嘎嘎'
}
// 应聘选手鸡
let chicken = {
    voice: '嘎嘎嘎'
}
// 合唱团成员数组
let choir = []
// 加入合唱团
function joinChoir(animal) {
    console.log(animal.voice)
    if(animal.voice === '嘎嘎嘎') {
        choir.push(animal)
    }
}
// 鸭子加入
joinChoir(duck)
// 鸡加入
joinChoir(chicken)
// 合唱团组队完成
console.log(choir)