Fe-interview: [js] 第9天 写一个判断数据类型的方法

Created on 24 Apr 2019  ·  34Comments  ·  Source: haizlin/fe-interview

第9天 写一个判断数据类型的方法

js

Most helpful comment

function type (obj) {
    return Object.prototype.toString.call(obj).replace(/\[object\s|\]/g,'');
}

console.log(type([]))  //"Array"
console.log(type(1))  //"Number"

All 34 comments

function myType(v){
    return Object.prototype.toString.call(v).replace(/^.{8}(.+)]$/,(m,$1)=> $1.toLowerCase());
}
  • typeof
    不能判读 数组 和 对象
  • toString()
Object.prototype.toString.call([])  //"[object Array]"
Object.prototype.toString.call({})  //"[object Object]"
toString.call() // "Array", "Function", "Object", "RegExp", "Date"
typeof obj // "Boolean", "Number", "String"
function type (obj) {
    return Object.prototype.toString.call(obj).replace(/\[object\s|\]/g,'');
}

console.log(type([]))  //"Array"
console.log(type(1))  //"Number"
 function isType(obj) {
    return (type) => {
        return Object.prototype.toString.call(obj) === `[object ${type}]`
    }
}

typeof 只能判断基本类型 string,number,boolean, undefined,object

  • null 会被判断成 object

比较全面的是使用 Object.prototype.toString 方法,只需要对返回值进行字符串分割即可

const typeCheck = (obj) => {
  const typeStr = Object.prototype.toString.call(obj);
  return typeStr.toLowerCase().slice(8, typeStr.length - 1);
};

console.log(typeCheck("str"));
console.log(typeCheck(1));
console.log(typeCheck(() => null));
console.log(typeCheck({a: 1}));
console.log(typeCheck([1, 2, 3]));
console.log(typeCheck(new Set([1,2,3])));
function isTypeOf(obj, type) {
  return Object.prototype.toString.call(obj)
    .replace(/[\[|\]]/g, "")
    .substr(7).toLowerCase() === type.toLowerCase();
}

function myType(v){
return Object.prototype.toString.call(v).replace(/^.{8}(.+)]$/,(m,$1)=> $1.toLowerCase());
}
请问这个正则是什么意思

function types (obj) {
return Object.prototype.toString.call(obj).replace(/[object\s|]/g, '');
}
console.log(type({}))
console.log(type(1))
console.log(type([]))

function getType(target){
let rs = Object.prototype.toString.call(target).split(' ')
return rs[1].substr(0, rs[1].length-1)
}

const getDataType = el => {
    const dataType = Object.prototype.toString.call(el);
    return dataType.split(' ')[1].split(']')[0];
};
console.log(getDataType(123)); // Number
console.log(getDataType('123')); // String
console.log(getDataType(() => { })); // Function
console.log(getDataType([1, 2, 3])); // Array

typeof不足

❌众所周知原生typeof有很多不足如下所示:

typeof null // object
typeof /a/ // object
typeof new String('') // object
function A () {}
typeof (new A) //  'object'

✅我们期望能返回下面:

import type from '@careteen/type'
type(null) // null
type(/a/) // regexp
type(new String('')) // string
function A () {}
type(new A) //  A

实现并封装

将功能封装在@careteen/type,可前往查看支持类型以及测试用例。

下面写法支持

  • number, boolean, string, undefined, null, symbol
  • array, object, set, weakset, map, weakmap
  • function, class
  • regexp, date, math, promise
const _toString = Object.prototype.toString
const NULL = 'null'
const OBJECT = 'object'
const NUMBER = 'number'
const BOOLEAN = 'boolean'
const STRING = 'string'
const UNKNOW = 'unknow'

/**
 * 
 * @param {*} element 任意类型的变量
 * @param {Boolean} strict [default: false] 是否为严格模式
 * @return {String} 变量的真实类型
 */ 
export default function type (element, strict = false) {
  strict = !!strict

  // #1 fix typeof null === 'object'
  if (element === null) {
    return NULL
  }

  const eleType = typeof element

  // #2 return [number string boolean undefined symbol]
  if (eleType !== OBJECT) {
    return eleType
  }

  let eleRealType
  let eleRealTypeLower

  try {
    eleRealType = _toString.call(element).slice(8, -1)
    eleRealTypeLower = eleRealType.toLowerCase()
  } catch (e) {
    // #3 IE activie 对象
    return OBJECT
  }

  // #4 fix typeof new String('') === 'object' , expect 'string'
  if (eleRealTypeLower !== OBJECT) {
    // 严格模式下 会严格区分`number、string、boolean`的原始值和对象值
    // example `new String('') => 'String'`、`String('') => 'string'`
    if (strict && (eleRealTypeLower === NUMBER || eleRealTypeLower === BOOLEAN || eleRealTypeLower === STRING)) {
      return eleRealType
    }
    return eleRealTypeLower
  }

  if (element.constructor == Object) {
    return eleRealTypeLower
  }

  // #5 Object.create(null)
  try {
    // __proto__ 为部分早期浏览器
    if (Object.getPrototypeOf(element) === NULL || element.__proto__ === NULL) {
      return OBJECT
    }
  } catch (e) {
    // IE 无 Object.getPrototypeOf
  }

  // #6 function A () {}; new A
  try {
    const constructorName = element.constructor.name
    if (typeof constructorName === STRING) {
      return constructorName
    }
  } catch (e) {
    // No constructor
  }

  // function A() {}; A.prototype.constructor = null; new A
  return UNKNOW
}

有几个小问题

  • Object.prototype.toString 这里的toStringtoString()的区别是啥,toString()是原生对象提供的方法的话,如何描述toString
  • ([]).toString //ƒ toString() { [native code] } 在浏览器控制台输入的这个返回,表示toString被理解成一个函数,里面的native code又表示什么呢,是代表了原生Object上的部分还是重写之后的

    • (10).toString(2) // '1010' 不同的数据类型带有的toString()是有区别的,特别是数字型的可以做进位转换

function myType(v){
return Object.prototype.toString.call(v).replace(/^.{8}(.+)]$/,(m,$1)=> $1.toLowerCase());
}
请问这个正则是什么意思

console.log(Object.prototype.toString.call("abc"));  // [object String]

可以看到,对于打印的结果,前8个字符我们不要,并且需要将类型结果转换为小写的 string

const isType = (targe, type) => {
if(typeof targe !== 'object') return
const typeString = Object.prototype.toString.call(targe)

return `[object ${type}]` === typeString

}
isType([], 'Array') //true

//第9天 写一个判断数据类型的方法

function type(obj) {
  return Object.prototype.toString
    .call(obj)
    .split(" ")[1]
    .replace("]", "");
}

console.log(type([]));
console.log(type({}));
console.log(type(() => {}));
console.log(type(1));
console.log(type("1"));

Object.prototype.toString.call() 将目标转换成[object Null] 这种形式,然后截取

function type(obj) {
     return /^\[object (\w*)]$/.test(Object.prototype.toString.call(obj)) ? RegExp.$1 : 'unknown';
}

console.log(type('hello'));
console.log(type(1));
console.log(type(Number(1)));
console.log(type({}));
console.log(type([]));
console.log(type(new Date()));
console.log(type(Symbol()));
console.log(type(new RegExp()));
console.log(type(Math));
console.log(type(window));
console.log(type(null));
console.log(type(undefined));
console.log(type(new Error()));
console.log(type(Promise));

返回正则提取Object.prototype.toString.call(obj), 匹配出来的字符串。

function checkType(val) {
  return Object.prototype.toString.call(val).replace(/(\[object)|\]/g, '').toLowerCase()
}

console.log(checkType('sdf'))
console.log(checkType(123))
console.log(checkType([]))
console.log(checkType({}))
console.log(checkType(undefined))
console.log(checkType(null))
console.log(checkType(() => {}))
// string
// number
// array
// object
// undefined
// null
// function
var obj={age:18},str="hello",num=18,ary=[0,1,2];
var checkType=v=> Object.prototype.toString.call(v).replace(/object |\[|\]/g,"");
function getType(obj) {
    return Object.prototype.toString.call(obj).slice(8, -1).toLowerCase();
}

我个人常用的

// 写一个判断类型的方法

const Type = (function () {
    const types = {};
    const supperTypes = [
        'String',
        'Number',
        'Boolean',
        'Null',
        'Undefined',
        'Object',
        'Function',
        'Array',
        'Date'
    ];

    for (let type of supperTypes) {
      types[`is${type}`] = function (data) {
        return Object.prototype.toString.call(data) === `[object ${type}]`;
      }
    }

    return types;
})();

let str = '我是字符串';
let num = 123;
let bol = false;
let arr = [1,2,3];
let obj = {};
let func = class {};

console.log(Type.isString(str));
console.log(Type.isNumber(num));
console.log(Type.isBoolean(bol));
console.log(Type.isArray(arr));
console.log(Type.isObject(obj));
console.log(Type.isFunction(func));

/**
 * true
 * true
 * true
 * true
 * true
 * true
 */

我个人常用的

// 写一个判断类型的方法

const Type = (function () {
    const types = {};
    const supperTypes = [
        'String',
        'Number',
        'Boolean',
        'Null',
        'Undefined',
        'Object',
        'Function',
        'Array',
        'Date'
    ];

    for (let type of supperTypes) {
      types[`is${type}`] = function (data) {
        return Object.prototype.toString.call(data) === `[object ${type}]`;
      }
    }

    return types;
})();

let str = '我是字符串';
let num = 123;
let bol = false;
let arr = [1,2,3];
let obj = {};
let func = class {};

console.log(Type.isString(str));
console.log(Type.isNumber(num));
console.log(Type.isBoolean(bol));
console.log(Type.isArray(arr));
console.log(Type.isObject(obj));
console.log(Type.isFunction(func));

/**
 * true
 * true
 * true
 * true
 * true
 * true
 */

加上Symbol和BigInt就完美了

Object.prototype.toString.call()

const getType = target => Object.prototype.toString.call(target).toLowerCase().slice(8,-1);
        function fn(obj) {
            if (typeof(obj) == 'object') {
                return Object.prototype.toString.call(obj).replace(/\[|object|\s|\]/g, '')
            }
            return typeof(obj);

        }

// 类型检测偏函数
const toString = Object.prototype.toString;
function isType (type) {
return function(obj) {
return toString.call(obj) === [object ${type}];
};
}
const isArray = isType('Array');
const isObject = isType('Object');
const isString = isType('String');
const isNull = isType('Null');

function myType(v){
return Object.prototype.toString.call(v).substr(8,).split(']')[0].toLowerCase()
}

toString.call() // "Array", "Function", "Object", "RegExp", "Date"
typeof obj // "Boolean", "Number", "String"

function getDataType(data) {
    return Object.prototype.toString.call(data).replace(/\[object\s+(\w+)\]/i, (match, $1) => {
        console.log(match, $1);
        return $1.toLocaleLowerCase();
    });
}
console.log(getDataType(1));
console.log(getDataType(''));
console.log(getDataType(true));
console.log(getDataType(null));
console.log(getDataType(undefined));
console.log(getDataType(Symbol(1)));
console.log(getDataType({}));
console.log(getDataType([]));
console.log(getDataType(function() {}));

有几个小问题

  • Object.prototype.toString 这里的toStringtoString()的区别是啥,toString()是原生对象提供的方法的话,如何描述toString

加括号是执行啊.不加只是引用而已

  • ([]).toString //ƒ toString() { [native code] } 在浏览器控制台输入的这个返回,表示toString被理解成一个函数,里面的native code又表示什么呢,是代表了原生Object上的部分还是重写之后的

机器码

@xcLtw

let x = ''; // null和undefined要单独处理
x.__proto__.constructor.toString()

获取构造函数的方式可以处理自定义类的情况 比如 new Person()

看来 我是对题目有误解
typeof()
instanceof()
Object.prototype.toString.call()

function checkType(o) {
  const match = Object.prototype.toString.call(o).match(/\w+(?=\])/);

  return match ? match[0].toLowerCase() : "unknown";
}

console.log(checkType({}));
console.log(checkType(123));
console.log(checkType("123"));
console.log(checkType([]));
console.log(checkType(new Map()));
console.log(checkType(function () {}));
console.log(checkType(Symbol()));
console.log(checkType(null));
console.log(checkType(undefined));

/**
object
number
string
array
map
function
symbol
null
undefined
 */
Was this page helpful?
0 / 5 - 0 ratings