深拷贝和浅拷贝
深拷贝:
- JSON.parse(JSON.Stringify(obj)) 此时会忽略
undefined
、symbol
和函数
- _.deepClone()
- jQuery.extend(true, {}, obj)
function deepClone(obj, hash = new WeakMap()){
if(obj == null) return obj //null或者undefined不拷贝
if(obj instanceof Date) return new Date(obj)
if(obj instanceof RegExp) return new RegExp(obj)
if(typeof obj !== 'object') return obj //不是对象不用深拷贝
if(hash.get(obj)) return hash.get(obj) //已经克隆过就返回之前的值,防止无限克隆
// 开始未克隆过的对象的拷贝
let cloneObj = new obj.construtor() //construtor获取到了obj的原型,也就是当前类本身
hash.set(obj, cloneObj) //记录obj被克隆
for(let key of obj){ //obj是个对象,对属性一一克隆
if(obj.hasOwnProperty(key)){ //检查对象是否具有指定的属性,并且该属性是对象自身的属性,而不是继承自原型链的属性。这可以避免拷贝从原型链上继承的属性,确保只拷贝对象自身定义的属性。
cloneObj[key] = deepClone(obj[key], hash) //确保obj[key]的值是对象的时候也被深拷贝
}
}
return cloneObj
}
浅拷贝:
- Object.assign({}, obj)
- slice(0)
- obj.concat()
- 拓展运算符
WeakMap
- WeakMap要求key值都为引用类型(Map可以为数值、引用类型和字符串)(引用类型包括Array、Object、Function等)
- WeakMap的方法包括set(参数【key,value】,只写key的时候会赋值undefined)\has(参数【key】,返回true/false)\get(参数【key】,获取对应的value值,当key为引用类型的时候,不一定指向同一地址,可能输出undefined)\delete(参数【key】,返回true/false),其方法参数也必须为引用类型
- WeakMap原型上没有【Symbol.iterator】,不能用遍历方法 entries(for(x of weakMap.entries())获取每对键值对)、foreach、values、keys、size
JavaScript的事件模型
原生事件模型
在html
和js
中设置元素.onclick=fn
,移除设置 元素.onclick=null
只支持冒泡,从下到上。同一个元素同一个类型事件只能绑定一个函数
标准事件模型
addEventListener(eventType, handler, false)
和removeEventListener(eventType, handler, false)
经历事件捕获、目标、事件冒泡阶段。第三个参数为是否采取事件捕获时进行处理
IE事件模型
attachEvent
和detachEvent
经历事件捕获、事件冒泡阶段
instanceof 和 typeof
typeof
- typeof 返回一个类型的字符串,只能识别除null外的基本类型,null会被识别成‘object’,引用类型只能识别function,其它都识别成‘object’
typeof obj
instanceof
-
instanceof 返回布尔值,不能识别基本类型,但是可以识别引用类型
-
x instanceof 类型
function myInstanceof(left, right){ if(typeof left !== 'object' || typeof left === null) return false //基本数据类型不能识别 let proto = Object.getPropertyOf(left) // getProtypeOf是Object对象自带的API,能够拿到参数的原型对象 while(true){ if(proto !== 'object') return false if(proto === right.prototype) return true //找到相同原型对象 proto = Object.getPropertyOf(proto) // 顺着原型链去找,直到找到相同的原型对象,返回true,否则为false } }
具体识别数据类型可以使用 Object.prototype.toString()
会返回字符串'[Object 类型]'
function getType(obj){
if(typeof obj !== 'object') return typeof obj //返回基本类型
return Object.prototype.toString.call(obj).replace(/^\[object (\S+)\]$/, '$1') //正则表达式返回具体类型
}