4

我已经习惯了 Java,所以当我尝试这样的事情时:

function subSection(pattern){
    this.total = 0;
    this.pattern = pattern;
    this.distance=0;
}

function enhancer(pattern){
    __proto__:subSection;
    this.pattern = pattern;
}

function silencer(pattern){
    __proto__:subSection;
    this.pattern = pattern;
}

var a = new enhancer("aaa");
document.write(a.distance)

我得到“未定义”。我以为我继承了总和距离数据成员

4

4 回答 4

3

不要使用__proto__,它是 Mozilla 的专有财产(被其他一些人复制)并且已被弃用。分配给 construtor.prototpye。

该行:

> __proto__:subSection;

没有给任何东西分配任何东西,它是一个标签 ( __proto__),后跟一个语句,该语句subSection是对未分配给任何东西的 subSection 函数的引用。

你好像不懂原型继承,试试 Douglas Crockford's Prototypal Inheritance in JavaScript

以下可能类似于您正在尝试做的事情,这里肯定有一千个类似的问题:

function SubSection(pattern) {
    this.pattern = pattern;
    this.total = 0;
    this.distance=0;
}

// Add a method to subSection.prototype
SubSection.prototype.getDistance = function() {
  return this.distance;
}

function Enhancer(pattern) {
    this.pattern = pattern;
}

// To make enhancer inherit from subSection, make its prototype
// an instance of subSection
Enhancer.prototype = new SubSection();

var a = new Enhancer("aaa");

document.write(a.getDistance()); // 0

哦,按照惯例,构造函数名称以大写字母开头。

于 2012-06-18T00:43:46.243 回答
3
function subSection(pattern){
    this.total = 0;
    this.pattern = pattern;
    this.distance=100;
}

function enhancer(pattern){
    this.__proto__=new subSection(pattern);
}

function silencer(pattern){
    this.__proto__=new subSection(pattern);
}

var a = new enhancer("aaa");
document.write(a.distance)​;

但正如所说,这只是 Mozilla 的专有财产RobG

演示。

更新:

function subSection(pattern){
    this.total = 0;
    this.pattern = pattern;
    this.distance=100;
}

function enhancer(pattern){
    function F(){};
    F.prototype = new subSection(pattern); // inherited subSection
    return new F();    
}

function silencer(pattern){
    function F(){};
    F.prototype = new subSection(pattern); // inherited subSection
    return new F();
}

var a = new enhancer("aaa");
document.write(a.distance)​;

演示。

有用的链接: 这里这里

于 2012-06-18T00:44:58.987 回答
0

你应该为你的对象使用原型继承。我会采用您的增强器对象并像这样定义它:

    //create Enhancer object
function Enhancer(pattern){
    this.subSection(pattern);    
}

//extend Enhancer with object methods
Enhancer.prototype = {

   subSection: function(pattern){
         this.pattern = pattern;
         this.total = 0;        
         this.distance=0;
  }

};

所以这就是我在这段代码中要做的事情:

  1. 我正在用一个函数定义 Enhancer 对象。请注意,我将“Enhancer”大写以表示此数据结构的“对象”。
  2. 我将“模式”值传递给对象并使用它来调用 Enhancer.subSection(); 我可以调用 .subSection() 作为 Enhancer 对象的方法,因为我将它定义为使用 .prototype 的方法。

这是这种方法的一个工作小提琴示例

于 2012-06-18T00:45:33.947 回答
0

一般来说,应该在构造函数中而不是在构造函数中定义对象的每个实例的属性,例如totaldistance旨在被初始化为完全相同的值。subSectionprototype

对象prototype基本上是一个“模板”,该对象的每个实例都基于该模板。每个实例都有在prototype.

因此这三个“类”(JavaScript 没有像 Java 这样的经典继承语言中定义的类,但有时习惯这些语言的人更容易使用该术语)应该声明如下:

function subSection(pattern) {
    this.pattern = pattern;
}

function enhancer(pattern) {
    this.pattern = pattern;
}

function silencer(pattern) {
    this.pattern = pattern;
}

移出构造函数并total进入distance原型:subSectionsubSection

subSection.prototype.total = 0;
subSection.prototype.distance = 0;

下一步是在 之间设置原型继承subSectionenhancersilencer使用无操作函数作为它们之间的一种代理:

function fn() {}
fn.prototype = subSection.prototype;

enhancer.prototype = new fn();
silencer.prototype = new fn();

最后,将和原型的constructor属性设置为正确的对象,以便实例的属性引用正确的构造函数。如果我们不采取这一步,那么or的任何实例都会错误地引用构造函数。enhancersilencerconstructorenhancersilencersubSection

enhancer.prototype.constructor = enhancer;
silencer.prototype.constructor = silencer;

现在我们可以实例化enhancerandsilencer对象,生成的实例将具有totalanddistance属性以及constructor引用相应对象的属性。

var a, b;
a = new enhancer('aaaa');
b = new silencer('bbbb');
console.log(a.total + ', ' + a.distance); // 0, 0
console.log(b.total + ', ' + b.distance); // 0, 0
console.log(a.constructor); // (string representation of enhancer constructor)

我们fn在继承过程中使用函数作为代理的原因是因为一个对象应该能够从另一个对象继承,而该对象不一定具有相同的构造函数参数集。

假设我们有以下两个构造函数:

function Person(name, age, hometown) {
    this.name = name;
    this.age = age;
    this.hometown = hometown;
}

function Employee(name, company, title) {
    this.name = name;
    this.company = company;
    this.title = title;
}

EmployeePerson即使它们不共享同一组构造函数参数,也应该能够继承自。如果我们简单地将Employee.prototype的新实例设置为相等,PersonEmployee原型将具有三个未定义的属性name和。agehometown

Employee.prototype = new Person; // name, age and hometown are undefined
var e = new Employee('John Smith', 'New York Times', 'editor'); // e's prototype has undefined properties name, age and hometown

通过使用 no-op 函数fn(我们几乎可以将它命名为任何我们想要的名称),我们最终为每个实例都提供了一个干净的原型,因为fn作为构造函数不需要任何参数。

这不是必需的,但它是设置原型继承的一种更简洁的方法:没有太多理由将带有未定义属性的原型弄乱。

于 2012-06-18T03:20:58.647 回答