js类型检测方法

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()这四个方法

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,457评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,837评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,696评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,183评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,057评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,105评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,520评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,211评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,482评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,574评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,353评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,897评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,489评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,683评论 2 335