JavaScript——数据类型判断方法汇总

1. typeof

// 1.typeof 数组、对象和null都会被视为object 其他类型都判定正确
console.log(typeof {}); // object
console.log(typeof []); // object
console.log(typeof null); // object
console.log(typeof function () {}); // function
console.log(typeof 1); // number
console.log(typeof true); // boolean
console.log(typeof "str"); // string
console.log(typeof undefined); // undefined
console.log(typeof Symbol()); // symbol

根据上面的结果可以看到数组、对象和null都会被视为object,其他类型都能判定正确。

2. instanceof

它的原理是:判断在其原型链中能否找到该类型的原型

console.log(2 instanceof Number); // false
console.log(true instanceof Boolean); // false
console.log("str" instanceof String); // false

console.log([] instanceof Array); // true
console.log(function () {} instanceof Function); // true
console.log({} instanceof Object); // true
console.log(null instanceof Object); // false  这是因为null是原型链的尽头 它没有后续原型链 更不可能找到Object类型的原型

根据上面的结果可以看到 instanceof只能正确判断引用类型,基本数据类型无法判定。

需要注意的是:null instanceof Object结果是false,因为null是原型链的尽头,它没有后续原型链,更不可能找到Object类型的原型。

3. constructor

它的原理是:**除了null之外,任何对象都会在其prototype/__proto__上有一个constructor属性,而constructor属性返回一个引用,这个引用指向创建该对象的构造函数,而NumberBooleanStringArray都属于构造函数。**因此通过construct和构造函数就能判断类型是否符合。

console.log((2).constructor);  // ƒ Number() { [native code] }  Number构造函数
console.log((2).constructor === Number);  // true
console.log((true).constructor === Boolean);  // true
console.log(("str").constructor === String);  // true
console.log(([]).constructor === Array);  // true
console.log((function () {}).constructor === Function);  // true
console.log(({}).constructor === Object);  // true
// console.log((null).constructor === Object);  // 会报错 原因是null不存在constructor
// console.log((undefined).constructor === Object);  // 会报错 原因是undefined不存在constructor
// console.log((null).constructor); // 会报错
// console.log((undefined).constructor); // 会报错

从上面的结果看到,constructor除了不能判断nullundefined外,其它类型都能判断

需要注意的是,如果创建的对象的原型被改变了,constructor就不能用来判断数据类型了。

function Fn() {}
console.log(Fn.prototype.constructor); // f Fn() {}
Fn.prototype = new Array()
console.log(Fn.prototype.constructor); // ƒ Array() { [native code] }
let f = new Fn();
console.log(f.constructor); // ƒ Array() { [native code] }
console.log(f.__proto__); // ƒ Array() { [native code] }
console.log(f.constructor === Fn); // false
console.log(f.constructor === Array); // true

扩展知识:constructor的两个作用:

  1. 判断数据类型。
  2. 对象实例通过construct对象访问它的构造函数。

4. Object.prototype.toString.call()

它的原理是:对象原型上的toString方法会获取当前对象的类型然后返回[object Type]字符串,由于部分内置对象对toString重写了,因此需要调用.call()来利用原本的toString函数,.call(args)方法实现让调用call方法的对象的this指向传的参数args

let a = Object.prototype.toString;
console.log(a.call(2)); // [object Number]
console.log(a.call(2) == Number); // false
console.log(a.call(2) == "[object Number]"); // true

console.log(a.call(true)); // [object Boolean]
console.log(a.call(true) == Boolean); // false
console.log(a.call(true) == "[object Boolean]"); // true

console.log(a.call("str")); // [object String]
console.log(a.call("str") == String); // false
console.log(a.call("str") == "[object String]"); // true

console.log(a.call(new Date())); // [object Date]
console.log(a.call(new Date()) == Date); // false
console.log(a.call(new Date()) == "[object Date]"); // true

console.log(a.call([])); // [object Array]
console.log(a.call(function () {})); // [object function]
console.log(a.call({})); // [object Object]
console.log(a.call(undefined)); // [object undefined]
console.log(a.call(null)); // [object Null]

通过上面代码可以看到,Object.prototype.toString.call()可以验证任何类型。

5. 封装一个类型验证的方法

大型项目中往往会使用Object.prototype.toString.call()封装一个isType方法来验证类型,封装代码如下:

function isType(data, type) {
  const typeObj = {
    "[object String]": "string",
    "[object Number]": "number",
    "[object Boolean]": "boolean",
    "[object Null]": "null",
    "[object Undefined]": "undefined",
    "[object Object]": "object",
    "[object Array]": "array",
    "[object Function]": "function",
    "[object Date]": "date", // Object.prototype.toString.call(new Date())
    "[object RegExp]": "regExp",
    "[object Map]": "map",
    "[object Set]": "set",
    "[object HTMLDivElement]": "dom", // document.querySelector('#app')
    "[object WeakMap]": "weakMap",
    "[object Window]": "window", // Object.prototype.toString.call(window)
    "[object Error]": "error", // new Error('1')
    "[object Arguments]": "arguments",
  };
  let name = Object.prototype.toString.call(data); // 借用Object.prototype.toString()获取数据类型
  let typeName = typeObj[name] || "未知类型"; // 匹配数据类型
  return typeName === type; // 判断该数据类型是否为传入的类型
}

下面我们可以测试一下封装结果:

console.log(
  isType({}, "object"), // true
  isType([], "array"), // true
  isType(new Date(), "object"), // false
  isType(new Date(), "date") // true
);

6. 总结

方法名 效果
typeof 数组、对象和null都会被视为object,其他类型都能判定正确
instanceof 只能正确判断引用类型,基本数据类型无法判定
constructor 除了不能判断nullundefined外,其它类型都能判断
Object.prototype.toString.call() 可以判断所有类型,但是返回结果是字符串【最推荐,封装isType

你可能感兴趣的:(面试,JavaScript,javascript,原型模式,开发语言,前端,面试,js类型)