JavaScript中使用Object.create()实现继承?

15

如何使用Object.create()进行继承?我尝试了以下代码,但都没有成功:

var B = function() {};
var A = function() {};
A = Object.create(B);
A.prototype.C = function() {};
而且
var B = function() {};
var A = function() {};
A.prototype.C = function() {};
A = Object.create(B);

var B = function() {};
A = Object.create(B);
var A = function() {};
A.prototype.C = function() {};

什么都不起作用。我应该如何使用这个新的Object.create()函数?


7个回答

30

在JavaScript中有几种实现继承的方式。

构造函数继承。如果你不需要调用超类型的构造函数,则可以使用该方法:

function Rectangle(length, width) { 
    this.length = length;
    this.width = width;
}

Rectangle.prototype.getArea = function() {
    return this.length * this.width;
};

// inherits from Rectangle
function Square(size) { 
    this.length = size;
    this.width = size;
}

Square.prototype = Object.create(Rectangle.prototype);

var rect = new Rectangle(6, 8);
var square = new Square(10);

console.log(rect.getArea());                // 48
console.log(square.getArea());              // 100
console.log(rect instanceof Rectangle);     // true
console.log(rect instanceof Object);        // true
console.log(square instanceof Square);      // true
console.log(square instanceof Rectangle);   // true
console.log(square instanceof Object);      // true

构造函数偷取。用于需要调用超类构造函数的情况:

function Rectangle(length, width) { 
    this.length = length;
    this.width = width;
}

Rectangle.prototype.getArea = function() {
    return this.length * this.width;
};

// inherits from Rectangle
function Square(size) { 
    Rectangle.call(this, size, size);
}

Square.prototype = Object.create(Rectangle.prototype);

var rect = new Rectangle(6, 8);
var square = new Square(10);

console.log(rect.getArea());                // 48
console.log(square.getArea());              // 100
console.log(rect instanceof Rectangle);     // true
console.log(rect instanceof Object);        // true
console.log(square instanceof Square);      // true
console.log(square instanceof Rectangle);   // true
console.log(square instanceof Object);      // true

我在某处看到了 Square.prototype.constructor = Square;,它是否不需要? - c0ming

22

Object.create()被用来继承对象,而不是像你试图做的那样继承构造函数。它基本上创建一个新对象,并将旧对象设置为其原型链父级。

var A = function() { };
A.prototype.x = 10;
A.prototype.say = function() { alert(this.x) };

var a = new A();
a.say(); //alerts 10

var b = Object.create(a);
b.say(); //alerts 10
b.x = 'hello';
b.say(); //alerts 'hello'

为了确保 b 不仅仅是 a 的克隆,

a.x = 'goodbye';
delete b.x;
b.say(); //alerts 'goodbye'

该死,那么它不适合我的情况。我需要定义一个继承另一个类的“类”。 - Tower
原型继承的重点在于你不必强制区分“类”和“对象”,因为类也是一个对象。 - Kos
我希望有一个 Object.clone(obj) 方法,它能够产生与 JSON.parse(JSON.stringify(obj)) 相同的结果。 - trusktr
有一个叫做Object.assign()的函数,但我希望它被称为Object.clone()。对我来说,Object.assign()感觉很奇怪。 - code_monk
你将如何创建另一个从a继承的类b的实例,并且:
  1. 不会改变先前的b实例
  2. 将在新的10个实例中重用b的代码?
- Artem A

17

我用于此的模式是将每个类型封装在一个模块中,并公开createprototype属性,如下所示:

var Vehicle = (function(){
        var exports = {};
        exports.prototype = {};
        exports.prototype.init = function() {
                this.mph = 5;
        };
        exports.prototype.go = function() {
                console.log("Going " + this.mph.toString() + " mph.");
        };

        exports.create = function() {
                var ret = Object.create(exports.prototype);
                ret.init();
                return ret;
        };

        return exports;
})();

然后我可以像这样构建派生类型:

var Car = (function () {
        var exports = {};
        exports.prototype = Object.create(Vehicle.prototype);
        exports.prototype.init = function() {
                Vehicle.prototype.init.apply(this, arguments);
                this.wheels = 4;
        };

        exports.create = function() {
                var ret = Object.create(exports.prototype);
                ret.init();
                return ret;
        };

        return exports; 

})();

使用这种模式,每种类型都有自己的create()函数。


跟进:最近我如果感觉需要创建类似的东西,我会使用Coffeescript;如果不需要,我会使用匿名对象。 - Sean McMillan

0

虽然已经晚了几年,但对于其他遇到同样问题的人来说,你可以在Firefox和Chrome中使用Object.assign。

在这个例子中,当使用create创建Cube时。首先,Object.create(this)将创建带有z属性的对象,然后使用Object.assign(obj, Square.create(x,y))调用Square.create并返回并将其附加到存储在obj中的Cube中。

 var Square = {
        x: 0,
        y: 0,

        create: function(x,y) {
            var obj = Object.create(this);
            obj.x = x;
            obj.y = y;
            return obj;
        }
    };

 var Cube = {

        z: 0,

        create:function(x,y,z) {
            var obj = Object.create(this);
            Object.assign(obj, Square.create(x,y)); // assign(target,sources...)
            obj.z = z;
            return obj;
        }
    };

// Your code
var MyCube = Cube.create(20,30,40);
console.log(MyCube);

0

Douglas的Object.create的原始文档在这里http://javascript.crockford.com/prototypal.html。确保您已经包含了该方法的定义。

if (typeof Object.create !== 'function') {
    Object.create = function (o) {
        function F() {}
        F.prototype = o;
        return new F();
    };
}

不建议使用该实现方式,请参阅:https://dev59.com/5VTTa4cB1Zd3GeqPw-kr - zack

0

你可以自己定义Object.create,但如果它不是本地的,你将不得不处理在你用于对象的每个for in循环中枚举它。

到目前为止,只有新的Webkit-Safari5和Chrome原生支持它。


3
Object.createObject 的一个属性,而不是 Object.prototype 的属性,因此自己定义它并不能将其添加到所有对象的枚举属性列表中。 - kpozin

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接