SOURCE

/**
 * 1 constructor === Array
 * 2 hasOwnProperty
 * JavaScript 并没有保护 hasOwnProperty 这个属性名,
 * 因此,当某个对象可能自有一个占用该属性名的属性时,
 * 就需要使用外部的 hasOwnProperty 获得正确的结果
 */
function deepClone(source) {
    // 基本数据类型直接跳出循环
    if (typeof source !== 'object' || typeof source === null) {
        return source
    }
    // 判断复制的目标是数组还是对象
  const targetObj = source.constructor === Array ? [] : {};
  for(let keys in source){ // 遍历目标
    if(source.hasOwnProperty(keys)){
      // 如果值是对象,就递归一下
      if(source[keys] && typeof source[keys] === 'object'){
        // targetObj[keys] = source[keys].constructor === Array ? [] : {};
        targetObj[keys] = deepClone(source[keys]);
      }else{ // 如果不是,就直接赋值
        targetObj[keys] = source[keys];
      }
    } 
  }
  return targetObj;
}

const a = [{b: 11}, 123]
const o = {a: 111, b: 222}
const b = '12346'
console.log(deepClone(a))
console.log(deepClone(o))
console.log(deepClone(b))


console.log(typeof [])

const obj1 = {
    foo: 1111,
}
// 修改 hasOwnProperty
const obj2 = {
    hasOwnProperty: function(){
        return false
    },
    foo: 123,
}
console.log(obj1.hasOwnProperty('foo'), 123)
console.log(obj2.hasOwnProperty('foo'), 123)

// 解决 修改风险 两种方案
console.log(
    ({}).hasOwnProperty.call(obj2, 'foo')
    )
console.log(
    Object.prototype.hasOwnProperty.call(obj2, 'foo')
)

console.log(
    Object.prototype.toString.call([]).slice(7,-1),
    Object.prototype.toString.call({}).slice(7,-1),
    Object.prototype.toString.call(()=>{}).slice(7,-1),
)
console 命令行工具 X clear

                    
>
console