1、安全的类型检测
Object.prototype.toString.call(obj) => "[object NativeConstructorName]"
1 /** 2 * 判断变量的类型 3 * @param {*} obj 需要判断的变量 4 * @return string "boolean/number/string/function/array/date/regExp/undefined/null/object" 5 */ 6 function getType (obj) { 7 const class2Type = { 8 '[object Boolean]': 'boolean', 9 '[object Number]': 'number', 10 '[object String]': 'string', 11 '[object Function]': 'function', 12 '[object Array]': 'array', 13 '[object Date]': 'date', 14 '[object RegExp]': 'regExp', 15 '[object Undefined]': 'undefined', 16 '[object Null]': 'null', 17 '[object Object]': 'object' 18 } 19 return class2Type[Object.prototype.toString.call(obj)] || 'object' 20 }
2、判断一个对象是否是window对象
1 // 判断obj是否是window对象 2 function isWindow (obj) { 3 return obj !== null && obj === obj.window 4 }
3、判断一个对象是否是数组
1 // 判断一个对象是否是数组 2 function isArray (obj) { 3 return Array.isArray ? Array.isArray(obj) : getType(obj) === 'array' 4 }
4、判断一个对象自身属性中是否具有指定的属性,非继承的属性
Object.prototype.hasOwnProperty.call('propsName')
1 o = new Object(); 2 o.prop = 'exists'; 3 o.hasOwnProperty('prop'); // 返回 true 4 o.hasOwnProperty('toString'); // 返回 false 5 o.hasOwnProperty('hasOwnProperty'); // 返回 false
1 // 判断一个对象是否是纯粹的对象(通过 "{}" 或者 "new Object" 创建的) 2 function isPlainObject (obj) { 3 // Object的hasOwnProperty()方法返回一个布尔值,判断对象是否包含特定的自身(非继承)属性,true表示是自身的属性 4 const hasOwn = Object.prototype.hasOwnProperty 5 6 // 不拷贝非对象、DOM对象、window对象 7 if (!obj || getType(obj) !== 'object' || obj.nodeType || isWindow(obj)) { 8 return false 9 } 10 try { 11 // Not own constructor property must be Object 12 if (obj.constructor && 13 !hasOwn.call(obj, 'constructor') && 14 !hasOwn.call(obj.constructor.prototype, 'isPrototypeOf')) { 15 return false 16 } 17 } catch (e) { 18 // IE8,9 Will throw exceptions on certain host objects #9897 19 return false 20 } 21 22 // Own properties are enumerated firstly, so to speed up, 23 // if last one is own, then all properties are own. 24 var key 25 for (key in obj) {} 26 27 return key === undefined || hasOwn.call(obj, key) 28 }
5、深浅拷贝
1 // 用JQ中的extend的方法来进行对象的深浅拷贝 2 export function merge () { 3 let options 4 let name 5 let src 6 let copy 7 let copyIsArray 8 let clone 9 let target = arguments[0] || {} // 获取第一个参数的值 10 let i = 1 11 let length = arguments.length // 获取传入参数的个数 12 let deep = false // 深浅拷贝标识,true表示深拷贝,false表示前拷贝 13 14 // 判断第一个参数是否是boolean值,如果是,那么应该从第3个参数开始进行深拷贝,否则进行浅拷贝 15 // merge(deep,target,source1,source2...) 16 if (typeof target === 'boolean') { 17 deep = target 18 i = 2 19 target = arguments[1] || {} // 获取目标源 20 } 21 22 // 对目标源target进行判断 23 if (typeof target !== 'object' && getType(target) !== 'function') { 24 target = {} 25 } 26 27 // 如果只传入两个参数,没有源数据 28 // merge(true,{}) 29 if ( length === i ) { 30 --i; 31 } 32 33 for (; i < length; i++) { 34 // 处理非空的源参数 35 if ((options = arguments[i]) !== null) { 36 // 获取源参数中的key值 37 for (name in options) { 38 // 通过key值获取目标源和源中的值 39 src = target[name] 40 copy = options[name] 41 42 // 避免死循环 43 if (target === copy) { 44 continue 45 } 46 // 深拷贝,只拷贝纯粹的obj或者数组 47 if (deep && copy && (isPlainObject(copy) || (copyIsArray = isArray(copy)))) { 48 // 拷贝的是数组 49 if (copyIsArray) { 50 copyIsArray = false 51 clone = src && isArray(src) ? src : [] 52 } else { 53 clone = src && isPlainObject(src) ? src : {} 54 } 55 target[ name ] = merge(deep, clone, copy) 56 } else if (copy !== undefined) { 57 target[ name ] = copy 58 } 59 } 60 } 61 } 62 return target 63 }
PS:使用JSON.stringify()和JSON.parse()也可以实现深拷贝,也可以使用JSON.stringify来判断两个对象是否相等。