原生实现 ES5 的 Object.create() 方法
答案:
Object.create() 方法创建一个新的对象,使用现有对象来提供新创建的对象的 __proto__ 属性。返回一个新对象,带着指定的原型对象和属性。
Object.create(proto[, propertiesObject])
proto
新创建对象的原型对象。
propertiesObject
可选。如果没有指定为 undefined
,则是要添加到新创建对象的不可枚举(默认)属性(即其自身定义的属性,而不是其原型链上的枚举属性)对象的属性描述符以及相应的属性名称。这些属性对应Object.defineProperties()
的第二个参数。如果propertiesObject
参数是 null
或非原始包装对象,则抛出一个 TypeError
异常。
实现:
简单版:
//创建一个对象,使其 __proto__ 指向传入的原型对象
function create(obj){
//创建一个空的构造函数
function F(){};
//将构造函数的 prototype 指向传入的对象
F.prototype = obj;
//返回构造函数的实例
return new F();
}
详细版:
Object.create = function(prototype,properties){
if(typeof prototype !== 'object'){
throw TypeError();
}
function Ctor(){};
Ctor.prototype = prototype;
var obj = new Ctor;
if(prototype){
obj.constructor = Ctor;
}
if(properties !== undefined){
if(properties !== Object(properties)){
throw TypeError();
}
Object.defineProperties(obj,properties);
}
return obj;
}
利用 Object.create() 方法可以实现继承:
// Shape - 父类(superclass)
function Shape() {
this.x = 0;
this.y = 0;
}
// 父类的方法
Shape.prototype.move = function(x, y) {
this.x += x;
this.y += y;
console.info('Shape moved.');
};
// Rectangle - 子类(subclass)
function Rectangle() {
Shape.call(this); // call super constructor.
}
// 子类续承父类
Rectangle.prototype = Object.create(Shape.prototype);
Rectangle.prototype.constructor = Rectangle;
var rect = new Rectangle();
console.log('Is rect an instance of Rectangle?',
rect instanceof Rectangle); // true
console.log('Is rect an instance of Shape?',
rect instanceof Shape); // true
rect.move(1, 1); // Outputs, 'Shape moved.'