【问题标题】:Javascript Inheritance of arguments and functionsJavascript参数和函数的继承
【发布时间】:2012-03-12 21:36:52
【问题描述】:

我有一个对象:

function Shape(color, position, coordinates){
    this.color = color;
    this.position = position;
    this.coordinates = coordinates;
    this.shrink = function(){
        reduce(coordinates);
    };
};

许多对象中的一个与前一个对象具有“是”关系。

function Sphere(color, position, coordinates, radius){
    this.radius = radius;
    this.role = function(){
        move(coordinates);
    };
};

还有一个单独的绘制形状的绘图函数

function draw(shape){
    moveTo(shape.position);
    setColor(shape.color);
    sketch(shape.coordinates);
}; 

我知道我应该尽可能尝试使用组合,但在某些情况下,例如上述情况,继承是一种更合适的模型。

如果没有框架,我如何尽可能简单地使用原型继承或任何其他形式来继承形状的功能和属性,这样我就不必为我创建的每种形状类型重新定义它们并且能够将参数传递给继承者对象的构造函数,因此它们被传递给被继承的对象。

编辑

我搜索了标题相似的帖子,但没有一个提供关于我的具体情况的示例,在构造函数中传递参数以及继承变量和函数。此外,我发现关于这个主题的答案倾向于提供多种选择,我正在寻找关于标准方法的更明确的答案(例如)

关于所谓的明确答案Performing inheritance in JavaScript,我发现如果我要按照原型函数中的描述定义我的所有属性,我的脚本会一团糟,而且它也没有说明如何处理传递给的参数构造函数。

【问题讨论】:

  • @Ajai,“......你肯定可以猜到这个(原型设计)......”你到底是什么意思?因为构造函数的标准原型属性只允许您定义“类变量”(如果我可以使用这个术语,因为缺少更好的术语)。
  • 为了公平起见,这个问题相当有用且清晰。另一方面,它没有显示出任何研究成果。
  • @whatsthebeef:注意在构造函数中设置方法时的语法错误;您已经颠倒了 function 和方法名称。由于您将属性设置为匿名函数,因此它应该是this.shrink = function() {...}。更好的是,在原型上设置方法:Shape.prototype.shrink = ...。
  • ... CMS 对“在 Javascript 中执行继承”的回答是权威性的。发布相同的问题,希望得到不同的答案并不是 SO 的工作方式;它应该是一个巨大的常见问题集合。小心你的语气; Ajai 可能不友善,但这并没有让你允许称呼他的名字。

标签: javascript inheritance prototypal-inheritance


【解决方案1】:

Javascript 没有任何原生结构来实现这一点。但是,有一些实用程序库可以帮助您实现这一目标。

如果您对此感兴趣,请查看 Dean Edward 的 Base 库:

http://dean.edwards.name/weblog/2006/03/base/

您可以按原样使用它来实现您想要的。无论如何,我可以推荐每个 javascript prorammer 阅读该代码并尝试了解它是如何工作的 - 它会让你成为一个更好的程序员。

一个非常简单的解决方案,完全不依赖于继承,也解决了传入参数的问题,就是使用对象字面量作为参数。要分配,您只需复制对象文字中的所有字段,如下所示:

//copy instance variables from source to target 
function copyInstanceVars(source, target){
    var p,v;
    for (p in source){
        if (source.hasOwnProperty(p)) {
            v = source[p];
            target[p] = v;
        }
    }
    return target;
}

//Shape, base class.
var Shape;
(Shape = function(config) {
    copyInstanceVars(config, this);  //copy instance variables from the config
}).prototype = {          //class members go in the prototype
    shrink: function(){
        reduce(coordinates);
    }
};

//Sphere, subclass of Shape
var Sphere;
(Sphere = function(config){
    Shape.apply(this, arguments);
}).prototype = copyInstanceVars(Shape.prototype, {  //inherit methods from Shape
    role: function(){
        move(coordinates);
    };
});

然后,在实例化对象时,您会:

var shape = new Shape({
    color: "blue",
    ...,
    coordinates: {x:10, y:20}
});

var sphere = new Sphere({
    color: "blue",
    ...,
    ...,
    radius: 10
});

因此,在这种情况下,实例变量只是您传递给构造函数的那些字段,而 copyInstanceVars 函数负责这个复制过程。 (那里的 hasOwnProperty 检查确保我们只获取实例变量)。

此示例还说明了如何使用相同的 copyInstanceVars 函数来继承方法。但是这次我们将它应用到构造函数的原型上(因为我们将方法“声明”为原型上的实例变量)

【讨论】:

  • 谢谢,我发现代码示例使其他语言中的标准和简单操作看起来有点笨拙。但是,我怀疑这是 javascript 继承的方式(这就是编写看似重复的问题的原因)。您发送的链接非常有趣,它比我更清楚地说明了我的问题,并确认我的问题并不完全是由于缺乏理解。我仍在研究那里的内容,也许我会尝试这个基础库,或者将所有变量推入原型链
【解决方案2】:

我通常发现寄生继承是 JavaScript 中最简单的选择:

function Sphere(color, position, coordinates, radius){
    var shape = new Shape(color, position, coordinates);
    shape.radius = radius;
    shape.role = function(){
        move(coordinates);
    };
    return shape;
};

最大的缺点是您不能使用原型链 - 将方法附加到 Sphere.prototype 不会使它们在新的 Sphere 实例上可用。

【讨论】:

  • 这是我开始的,但除了通过原型设计的可用性湖之外,另一个问题是;当有很多属性时,代码很快变得非常冗长。
  • 在这种情况下,移动到 options 对象而不是单个参数通常是个好主意:new Shape(options)、new Sphere(options) 等。然后您只需使用选项调用超级构造函数对象,并且您不必跟踪构造函数签名。
  • 我喜欢简单,显然忽略了安全隐患,并假设不会有深度继承树,我可以制作this.shape 并以这种方式公开原型函数。
猜你喜欢
  • 2021-08-31
  • 2014-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多