javascript中的继承模式

Posted

技术标签:

【中文标题】javascript中的继承模式【英文标题】:a pattern for inheritance in javascript 【发布时间】:2013-10-31 05:02:23 【问题描述】:

这是一个非常古老的主题,已经写了很多,但我还没有找到确切的答案,所以请多多包涵。

在花了一些时间试图了解 javascript 中的 newf.prototype 构造函数结构,并阅读了它如何成为一种原型语言,更不用说 Crockford 对这个主题的启发性 cmets 之后,我有得出的结论是,以下是在 JavaScript 中模拟传统的基于类的继承的一种更自然的方法,如果有人愿意的话:

// emphasise that there's no superclass instead of writing A = 
var A = Create.object(null);

// define the 'instance initializer', which half of what a constructor is
A.init = function(x, y) 
    this.x = x;
    this.y = y;
    return this;


// a method
A.sum = function() 
    return this.x + this.y;


// instantiate A
var a = Object.create(A).init(3);

// a subclass
var B = Object.create(A);

B.init = function(x, y, w) 
    A.init.call(this, x, y);
    this.w = w;
    return this;


B.weightedSum = function() 
    return (1.0 - this.w) * this.x + this.w * this.y;


// instantiate B
var b = Object.create(B).init(1, 2, 0.3);

// equivalent of `instanceof`
var bInstanceOfA = A.isPrototypeOf(b);

我喜欢它的地方在于它揭示了真正发生的事情,因为对象创建(适用于实例化和子类化)和初始化(仅适用于实例化)之间有明显的区别。创建基类和子类之间也存在对称性。代码不需要外部定义的函数或库,但也不是特别冗长。

因此,我的问题如下:那些对 JavaScript 有更多经验的人能否告诉我,我没有考虑的方法是否存在问题,或者它是否是一个好的模式?

【问题讨论】:

Object.create() 仅适用于 IE >= 9。 非常感谢...我相信添加它应该很简单,但如果有人愿意的话?我主要在节点中编程,所以这对我来说不是一个主要问题。还有什么问题吗? 无论如何Object.create() 都有一个polyfill。但是您不能在这种方法中使用 new 关键字。这扩展了对象,而不是原型。 最大的问题是“为什么”。甚至 Crockford 也表示,试图模仿经典继承并不是一个好主意,而且他认为在 javascript 中不需要复杂的继承方案。 是的,我同意,但是当您来自其他语言时,要清除传统 OOP 的头脑并不容易......这就是我喜欢这种方法的原因......没有“幕后魔术”发生就像new 这样你就可以开始习惯新的想法,而不是停留在旧的想法上 【参考方案1】:

使用这种方法会丢失 new 关键字。所以你不能说new A(128, 256)

但是您可以使用Object.create() 进行原型继承,并以这种方式使用new 关键字创建常规对象:

var Employee = function(name) 
    this.name = name;
    return this;
;

Employee.prototype = 
    doWork: function() 
        console.log('%s is doing some abstract work', this.name);
    
;

var Driver = function(name) 
    return Employee.call(this, name);
;

Driver.prototype = Object.create(Employee.prototype, 
    doWork: 
        value: function() 
            console.log('%s is driving a car', this.name);
        
    ,
    fixEngine: 
        value: function() 
            console.log('%s is fixing an engine', this.name);
        
    
);

var employee = new Employee('Jim');
var driver = new Driver('Bill');

employee.doWork(); // Jim is doing some abstract work 
driver.doWork(); // Bill is driving a car
driver.fixEngine(); // Bill is fixing an engine 

http://jsfiddle.net/f0t0n/HHqEQ/

【讨论】:

这就是我的全部观点,我不想使用new 关键字,因为它感觉就像是一种语言特性,它被标记为使JavaScript 看起来像它有类。我的模式提醒您,就 JavaScript 而言,实例只是初始化的子类(或子类是未初始化的实例:D)。 new 关键字掩盖了这种对称性。

以上是关于javascript中的继承模式的主要内容,如果未能解决你的问题,请参考以下文章

javascripe之继承

继承干货

JavaScript权威指南手记

javascript中的继承模式

Javascript设计模式第一课 Javascript中的继承

javascript 组合模式,对象冒充+原形链继承