文章

javascript

1.Object.create(null) 和 {} 的区别

Object.create(null) 创建的是一个干净的空对象,他的原型对象上是空的,而{}可以看作是“不干净”的空对象,因为他能访问到原型对象上的属性和方法,比如hasOwnProperty,toString等等。
为什么要使用Object.create(proto,
propertiesObject)?
1.Object.create(null) 可以自定义属性,而不必担心原型链上同名的属性或方法被覆盖。
2.跟{}比起来,在使用for-in遍历属性时候,它会遍历原型对象上的属性,而Object.create(null) 则不会遍历,因此有性能上的优势。

// {} 对象 查找自身属性
let obj1 = {...省略很多属性和方法...}
if(Object.prototype.hasOwnProperty.call(obj1,"toString")){
  console.log('yes')
}else{
console.log('no')
}

/***
 先确定一下这里对于{}来说,查找自身属性最好的方法是Object.prototype.hasOwnProperty.call,而不是对象自己去调用hasOwnProperty
*/

// 情况一:假如现在要查找obj1对象自身是否含有toString
let obj1 = {
    toString:function(){
        console.log('自身tostring方法')
    },
}
if(Object.prototype.hasOwnProperty.call(obj1,"toString")){
  console.log('yes')
}else{
  console.log('no')
}
if(obj1.hasOwnProperty("toString")){
    console.log('自己调用,yes')
}else{
    console.log('自己调用 no')
}

输出:  yes
       自己调用,yes
//ps:这种情况下,通过Object.prototype.hasOwnProperty.call或者自身调用hasOwnProperty都能正确返回结果。
//但是。。。。。。

//情况二:假如现在obj1对象上定义了一个名叫hasOwnProperty的属性
let obj1 = {
    toString:function(){
        console.log('自身tostring方法')
    },
    hasOwnProperty:function (){
        console.log("搁着卡bug呢")
    }
}
if(Object.prototype.hasOwnProperty.call(obj1,"toString")){
  console.log('yes')
}else{
  console.log('no')
}
if(obj1.hasOwnProperty("toString")){
    console.log('自己调用,yes')
}else{
    console.log('自己调用 no')
}
输出:  yes
      搁着卡bug呢
      自己调用 no
// 结果是明明ob1上有toString,obj1.hasOwnProperty("toString")缺判定为假,这是因为obj1自身的hasOwnProperty覆盖了原型对象上的hasOwnProperty方法,因此执行了自身的,并且由于自身的hasOwnProperty方法没有返回值,所以默认返回undefined,即判断的时候走了else条件。解决办法:return true。


// =Object.create(null) 对象 查找自身属性    
let obj2=Object.create(null,{
    toString:{
        writable:true,
        configurable:true,
        value:function(){
            console.log('xixi')     
        }
  }
})
  //if(obj2.hasOwnProperty('toString') console.log('没问题')  由于obj2是个干净的对象,obj2.__proto__为undefined,所以不能使用hasOwnProperty
  if(obj2.toString()){  //由于没有原型对象,obj2 上有什么自定义的属性就用自己的
    console.log('obj2 yes')
  }else{
  console.log('obj2 no')
  }
输出:
 xixi
 obj2 no  //输出no 是因为value 方法没有返回值

总结:

new Object()和字面量形式创建的{} 都是Object的实例,也就是说

obj.__proto__ === Object.prototype  // true
obj instanceof Object  //true

只不过字面量形式比new Object()高效一点,省去了new的__proto__ 指向和this.

而Object.create(proto, propertiesObject) ,第二个参数可选,它创建出来的对象的__proto__指向传入的原型对象

let obj1=Object.create(null)  
obj1.__proto__  // undefined


let obj={a:1}
let obj2=Object.create(obj)
obj2.__proto__ === obj  //true
obj2 instanceof Object// true   注意不是obj2 instancof obj  

License:  CC BY 4.0