js 数据类型判断

231 阅读2分钟

typeof

let s = 'string';
let n = 1;
let boo = true;
let nul = null;
let und = undefined;
let fun = function(){};
let obj = {
  name: 'huihui',
  age: 8
};
let arr = [1, 2, 3];
let sym = Symbol(1);
console.log(typeof(s));    // 'string'
console.log(typeof(n));    // 'number'
console.log(typeof(boo));  // 'boolean'
console.log(typeof(nul));  // 'object'
console.log(typeof(und));  // 'undefined'
console.log(typeof(fun))   // 'function'
console.log(typeof(obj))   // 'object'
console.log(typeof(arr))   // 'object'
console.log(typeof(sym))     // 'symbol'

typeof null 为什么返回 object

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

  • 000:对象
  • 010: 浮点数
  • 100: 字符串
  • 110: 布尔
  • 1: 整数

Object.prototype.toSting.call()

let s = 'string';
let n = 1;
let boo = true;
let nul = null;
let und = undefined;
let fun = function() {};
let obj = {
    name: 'huihui',
    age: 8
};
let arr = [1, 2, 3];
let sym = Symbol(1);

console.log(Object.prototype.toString.call(s));    // [object, String]
console.log(Object.prototype.toString.call(n));    // [object, Number]     
console.log(Object.prototype.toString.call(boo));  // [object, Boolean]
console.log(Object.prototype.toString.call(nul));  // [object, Null]
console.log(Object.prototype.toString.call(und));  // [object, Undefined]
console.log(Object.prototype.toString.call(fun));  // [object, Function]
console.log(Object.prototype.toString.call(obj));  // [object, Object]
console.log(Object.prototype.toString.call(arr));  // [object, Array]
console.log(Object.prototype.toString.call(sym));  // [object, Symbol]

instanceof

instanceof 主要的作用是判断一个实例是否属于某种类型

let person = function() {}
let notice = new person();
notice instanceof person    // true

instanceof 也可以判断一个实例是否属于其父类型或者祖先类型的实例

let person = function(){}
let programmer = function(){}
programmer.prototype = new person();
let notice = new programmer();
console.log(notice instanceof person)    // true
console.log(notice instanceof programmer)    // true

instanceof 实现原理

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__ 
    }
}

其实instanceof主要的实现原理就是只要右边变量的prototype在左边变量的原型链上即可。

  • 分析 Object instanceof Object
leftValue = Object.__proto__ = Function.prototype;
rightValue = Object.prototype;
// 第一次判断
leftValue != rightValue;
leftValue = Function.prototype.__proto__ = Object.prototype;
// 第二次判断
leftValue = rightValue
// 返回true
  • 分析 Function instanceof Function
leftValue = Function.__proto__ = Function.prototype;
rightValue = Function.prototype;
// 第一次判断
leftValue = rightValue;
// 返回true
  • 分析 Foo instanceof Foo
leftValue = Foo.__proto__ = Function.prototype;
rightValue = Foo.prototype;
// 第一次判断
leftValue = rightValue;
// 第二次判断
leftValue = Function.prototype.__proto__ = Object.prototype
leftValue != rightValue
// 第三次判断
leftValue = Object.prototype.__proto__ = null
leftValue != rightValue
// 返回false
  • 分析 Foo instanceof Object
leftValue = Foo.__proto__ = Function.prototype;
rightValue = Object.prototype;
// 第一次判断
leftValue != rightValue;
// 第二次判断
leftValue = Function.prototype.__proto__ = Object.prototype
leftValue = rightValue
// 返回true
  • 分析Foo instanceof Function
leftValue = Foo.__proto__ = Function.prototype;
rightValue = Function.prototype;
// 第一次判断
leftValue = rightValue;
// 返回true

总结

我们使用 typeof 来判断基本数据类型是 ok 的,不过需要注意当用 typeof 来判断 null 类型时的问题,如果想要判断一个对象的具体类型可以考虑用 instanceof,但是 instanceof 也可能判断不准确,比如一个数组,他可以被 instanceof 判断为 Object。所以我们要想比较准确的判断对象实例的类型时,可以采取 Object.prototype.toString.call 方法。

原型链.png