美文网首页
js类型检测方法

js类型检测方法

作者: HughesCZB | 来源:发表于2020-11-05 17:02 被阅读0次

    js有几种数据类型?

    String、Number、Boolean、undefined、Symbol、null、Object(引用类型)

    引用类型包括 Array Object Funtion

    几种区分类型的方法

    1. typeof: 只能区分前基本类型、symbol和function,不能区分Array、Object、null、Date等等

    2. constructor: 缺点 undefined和null无法检查

      var symbol = Symbol('1')
      var num = 2
      console.log(symbol.constructor === Symbol)
      console.log(num.constructor === Number)
      // 但是undefined 和 null都没有constructor
      
    3. Instanceof: 缺点常用写法的number、string、boolean等不能检测出来,symbol也是无法检查

      console.log(
          123 instanceof Number, //false
          'dsfsf' instanceof String, //false
          false instanceof Boolean, //false
          [1,2,3] instanceof Array, //true
          {a:1,b:2,c:3} instanceof Object, //true
          function(){console.log('aaa');} instanceof Function, //true
          undefined instanceof Object, //false
          null instanceof Object, //false
          new Date() instanceof Date, //true
          /^[a-zA-Z]{5,20}$/ instanceof RegExp, //true
          new Error() instanceof Error //true
      )
      

      Number,String,Boolean没有检测出他们的类型,但是如果使用下面的写法则可以检测出来:

      var num = new Number(123);
      var str = new String('dsfsf');
      var boolean = new Boolean(false);
      
    4. Object.prototype.toString.call(): 是目前最可靠的方法

      var toString = Object.prototype.toString;
      
      toString.call(123); //"[object Number]"
      toString.call('abcdef'); //"[object String]"
      toString.call(true); //"[object Boolean]"
      toString.call([1, 2, 3, 4]); //"[object Array]"
      toString.call({name:'wenzi', age:25}); //"[object Object]"
      toString.call(function(){ console.log('this is function'); }); //"[object Function]"
      toString.call(undefined); //"[object Undefined]"
      toString.call(null); //"[object Null]"
      toString.call(new Date()); //"[object Date]"
      toString.call(/^[a-zA-Z]{5,20}$/); //"[object RegExp]"
      toString.call(new Error()); //"[object Error]"
      

    那就用Object.prototype.toString.call写一个检测方法的函数

    function isType (type, value) {
      return Object.prototype.toString.call(value) === `[object ${type}]`
    }
    console.log(isType(1, 'Number'))
    

    优化:想让方法更具体,isNumber、isBoolean、isFunction 等

    const types = [
      'String',
      'Number',
      'Boolean',
      'Function',
      'Object',
      'Null',
      'Array',
      'Undefined'
    ]
    
    function isType (typing) {
      return function (value) {
        return Object.prototype.toString.call(value) === `[object ${typing}]`
      }
    }
    const utils = {}
    types.forEach(type => {
      utils[`is${type}`] = isType(type)
    })
    console.log(utils.isString(123))
    console.log(utils.isNumber(123))
    

    优化:柯里化函数,将两个参数分开

    const curring = (fn, arr = []) => {
      const len = fn.length
      return (...args) => {
        let newArgs = [...arr, ...args]
        if (newArgs.length === len) {
          return fn(...newArgs)
        } else {
          return curring(fn, newArgs)
        }
      }
    }
    function isType (type, value) {
      console.log(`[object ${type}]`)
      return Object.prototype.toString.call(value) === `[object ${type}]`
    }
    const newIsType = curring(isType)
    const isNumber = newIsType('Number')
    const isString = newIsType('String')
    console.log(isNumber(1)) // true
    
    // 柯里化也解决了经典的面试题 sum(1)(2,3,4)(5) // 15
    function sum(a,b,c,d,e) {
      return a + b + c + d + e
    }
    let newSum = curring(sum)
    newSum(1)(2,3,4)(5) // 15
    

    深拷贝和浅拷贝

    说到类型就不得不说到深拷贝和浅拷贝了,要考虑拷贝不同类型的值,是作为面试中常考的基本知识。

    什么是深拷贝和浅拷贝

    浅拷贝只是拷贝值,引用类型的数据,则是拷贝其内存地址

    深拷贝是拷贝值,对于引用类型的数据,会在内存中开辟新的空间,拷贝到这个空间里。

    // ...和Object.assign() 如果是多层的时候就是浅拷贝
    let obj = {name:'xx',age:{n:10}} // age实际存的是指针地址0xfff...
    let obj1 = {...obj}
    obj1.age.n = 200
    console.log(obj) // 此时obj.age.n 也变成了200
    

    浅拷贝有几种方法:

    • 对象: ..和Object.assign()

    • 数据: ...扩张运算符、slice()等

    实现深拷贝

    有一种深拷贝的方法: JSON.parse(JSON,stringrify(obj))。缺点是: 此方法只拷贝JSON语法的类型,不符合的直接就删掉了,比如undefined。

    实现深拷贝注意几点: 类型判断、引用类型拷贝、循环引用

    function deepClone (value, map = new WeakMap()) {
      if (value == null) return value
      if (value instanceof RegExp) return new RegExp(value)
      if (value instanceof Date) return new Date(value)
      if (typeof value !== 'object') {
        return value
      }
      if (map.has(value)) {
        return map.get(value)
      }
      map.set(value, value)
      let obj = new value.constructor()
      for (let key in value) {
        if (value.hasOwnProperty(key)) {
          obj[key] = deepClone(value[key], map)
        }
      }
      return obj
    }
    var obj = {
      a: 'a',
      b: 'b',
      c: {
        num: 0,
        name: 'c'
      }
    }
    obj.d = obj
    console.log(deepClone(obj))
    

    Map和WeakMap

    既然用到了WeakMap,说说他是什么,和Map有什么区别

    Map,hash集合,key可以是任意类型,而对象的key只能是字符串

    WeakMap只接受对象作为键名(null除外)。

    Map的键实际上是和内存地址绑定的,只要内存地址不一样,就是两个键,解决了hash碰撞的问题。

    WeakMap的key指向的key不计入垃圾回收机制。意思的不会因为你被引用就不回收你了

    它的键名所引用的对象都是弱引用,即垃圾回收机制不将该引用考虑在内。因此,只要所引用的对象的其他引用都被清除,垃圾回收机制就会释放该对象所占用的内存。也就是说,一旦不再需要,WeakMap 里面的键名对象和所对应的键值对会自动消失,不用手动删除引用。另外WeakMap没有遍历操作,只有get()、set()、has()、delete()这四个方法

    相关文章

      网友评论

          本文标题:js类型检测方法

          本文链接:https://www.haomeiwen.com/subject/kkqqpxtx.html