Object.create()、new Object()和{}的区别

此文首发于 lijing0906.github.iojavascript

平时代码中一定会使用对象,一般是用最直接的字面量方法建立var obj = {},最近在整理JS继承方式时遇到Object.create()也能够建立对象,另外,也能够用new Object()关键字建立。 那这三种方式有差异吗?java

直接字面量建立

var objA = {};
objA.name = 'a';
objA.sayName = function() {
    console.log(`My name is ${this.name} !`);
}
// var objA = {
// name: 'a',
// sayName: function() {
// console.log(`My name is ${this.name} !`);
// }
// }
objA.sayName();
console.log(objA.__proto__ === Object.prototype); // true
console.log(objA instanceof Object); // true
复制代码

new关键字建立

var objB = new Object();
// var objB = Object();
objB.name = 'b';
objB.sayName = function() {
    console.log(`My name is ${this.name} !`);
}
objB.sayName();
console.log(objB.__proto__ === Object.prototype); // true
console.log(objB instanceof Object); // true
复制代码

JS的指向问题中讲new绑定时讲了new操做符其实作了如下四步:git

var obj = new Object(); // 建立一个空对象
obj.__proto__ = F.prototype; // obj的__proto__指向构造函数的prototype
var result = F.call(obj); // 把构造函数的this指向obj,并执行构造函数把结果赋值给result
if (typeof(result) === 'object') {
    objB = result; // 构造函数F的执行结果是引用类型,就把这个引用类型的对象返回给objB
} else {
    objB = obj; // 构造函数F的执行结果是值类型,就返回obj这个空对象给objB
}
复制代码

这样一比较,其实字面量建立和new关键字建立并无区别,建立的新对象的__proto__都指向Object.prototype,只是字面量建立更高效一些,少了__proto__指向赋值和thisgithub

Object.create()

Object.create()方法建立一个新对象,使用现有的对象来提供新建立的对象的__proto__MDN函数

const person = {
  isHuman: false,
  printIntroduction: function () {
    console.log(`My name is ${this.name}. Am I human? ${this.isHuman}`);
  }
};
const me = Object.create(person); // me.__proto__ === person
me.name = "Matthew"; // name属性被设置在新对象me上,而不是现有对象person上
me.isHuman = true; // 继承的属性能够被重写
me.printIntroduction(); // My name is Matthew. Am I human? true
复制代码

Object.create(proto[, propertiesObject])post

  • proto必填参数,是新对象的原型对象,如上面代码里新对象me__proto__指向person。注意,若是这个参数是null,那新对象就不折不扣是个空对象,没有继承Object.prototype上的任何属性和方法,如hasOwnProperty()、toString()等。
var a = Object.create(null);
console.dir(a); // {}
console.log(a.__proto__); // undefined
console.log(a.__proto__ === Object.prototype); // false
console.log(a instanceof Object); // false 没有继承`Object.prototype`上的任何属性和方法,因此原型链上不会出现Object
复制代码
  • propertiesObject是可选参数,指定要添加到新对象上的可枚举的属性(即其自定义的属性和方法,可用hasOwnProperty()获取的,而不是原型对象上的)的描述符及相应的属性名称。
var bb = Object.create(null, {
    a: {
        value: 2,
        writable: true,
        configurable: true
    }
});
console.dir(bb); // {a: 2}
console.log(bb.__proto__); // undefined
console.log(bb.__proto__ === Object.prototype); // false
console.log(bb instanceof Object); // false 没有继承`Object.prototype`上的任何属性和方法,因此原型链上不会出现Object

// ----------------------------------------------------------

var cc = Object.create({b: 1}, {
    a: {
        value: 3,
        writable: true,
        configurable: true
    }
});
console.log(cc); // {a: 3}
console.log(cc.hasOwnProperty('a'), cc.hasOwnProperty('b')); // true false 说明第二个参数设置的是新对象自身可枚举的属性
console.log(cc.__proto__); // {b: 1} 新对象cc的__proto__指向{b: 1}
console.log(cc.__proto__ === Object.protorype); // false
console.log(cc instanceof Object); // true cc是对象,原型链上确定会出现Object
复制代码

Object.create()建立的对象的原型指向传入的对象。跟字面量和new关键字建立有区别。ui

  • 本身实现一个Object.create()
Object.mycreate = function(proto, properties) {
    function F() {};
    F.prototype = proto;
    if(properties) {
        Object.defineProperties(F, properties);
    }
    return new F();
}
var hh = Object.mycreate({a: 11}, {mm: {value: 10}});
console.dir(hh);
复制代码

总结

  • 字面量和new关键字建立的对象是Object的实例,原型指向Object.prototype,继承内置对象Object
  • Object.create(arg, pro)建立的对象的原型取决于argargnull,新对象是空对象,没有原型,不继承任何对象;arg为指定对象,新对象的原型指向指定对象,继承指定对象
相关文章
相关标签/搜索