5

我一直在尝试掌握 OO JavaScript 并创建了一个简单的示例。

function BasePage(name) {
    this.init(name);
}

BasePage.prototype = {
    init: function(name) {
       this.name = name; 
    },
    getName: function() {
        return this.name;
    }
}

function FaqPage (name, faq) {
    this.init(name, faq);
}

FaqPage.prototype = new BasePage();

FaqPage.prototype = {
    init: function(name, faq) {
        BasePage.prototype.init.call(this, name);
        this.faq = faq; 
    },
    getFaq: function() {
        return this.faq;
    }
}

var faqPage = new FaqPage('Faq Page', 'Faq');

var text = faqPage.getName() + ' ' + faqPage.getFaq();
$('body').text(text);

运行此结果会导致以下消息:

未捕获的类型错误:对象#<Object>没有方法“getName”

我想知道的是如何getName()在超类中调用该方法而不必在子类中覆盖和调用它?

另外,如果您认为这种方法不好/好。

4

4 回答 4

6

发生该错误是因为即使您已将FaqPage的原型设置为 的实例BasePage,您的下一行也会立即覆盖它。所以FaqPage不是继承自BasePage. 将属性/方法添加到FaqPage的原型,而不是再次定义它:

FaqPage.prototype.init = function(name, faq) {
    BasePage.prototype.init.call(this, name);
    this.faq = faq; 
}
FaqPage.prototype.getFaq = function() {
    return this.faq;
}
于 2013-05-19T16:00:55.480 回答
2

第一行是对的,您从基础对象创建了一个原型。

FaqPage.prototype = new BasePage();

但是然后你覆盖它,所以不再继承基础对象

FaqPage.prototype = {
    init: function(name, faq) {
        BasePage.prototype.init.call(this, name);
        this.faq = faq; 
    },
    getFaq: function() {
        return this.faq;
    }
}

而不是定义整个原型,只覆盖单个函数:

FaqPage.prototype.init = function(name, faq) {
    BasePage.prototype.init.call(this, name);
    this.faq = faq; 
};

FaqPage.prototype.getFaq = function() {
    return this.faq;
};
于 2013-05-19T16:08:24.167 回答
1

如果继承是你所追求的,据我所知,在 JavaScript 中实现它并不是很简单。我使用了 John Resig 的这个片段,它就像一个魅力。http://ejohn.org/blog/simple-javascript-inheritance/

在你的情况下,这就是它的工作方式,

基页

var BasePage = Class.extend({
  init: function(name){
     this.name = name;
  },
 getName: function(){
     return this.name;
 }
});

FaqPage 类继承 BasePage

var FaqPage = BasePage.extend({
  init: function(name, faq){
    this._super( name );
    this.faq = faq;
  },
  getFaq: function() {
    return this.faq;
  }
});

接着

var faqPage = new FaqPage('Faq Page', 'Faq');
var text = faqPage.getName() + ' ' + faqPage.getFaq();
$('body').text(text);

当然,要使其工作,您必须在我链接的页面上包含实现代码。

这是小提琴,http://jsfiddle.net/c8yjY/

于 2013-05-19T16:20:11.453 回答
1

我感觉到你的痛苦。正如其他人所提到getName的,是undefined因为您覆盖了prototypeof FaqPage。因此,我不会重复那个解释。

话虽如此,我确实同意将prototype方法封装在单个范围内是件好事。或许您应该为此目的使用 JavaScript 库。最小的一个是augment。实际上它只有 17 行长:

Function.prototype.augment = function (body) {
    var base = this.prototype;
    var prototype = Object.create(base);
    body.apply(prototype, Array.from(arguments, 1).concat(base));
    if (!Object.ownPropertyOf(prototype, "constructor")) return prototype;
    var constructor = prototype.constructor;
    constructor.prototype = prototype;
    return constructor;
};

(function funct() {
    var bind = funct.bind;
    var bindable = Function.bindable = bind.bind(bind);
    var callable = Function.callable = bindable(funct.call);
    Object.ownPropertyOf = callable(funct.hasOwnProperty);
    Array.from = callable([].slice);
}());

如果您使用以下代码,您的代码将如下所示augment

var BasePage = Object.augment(function () {
    this.constructor = function (name) {
        this.name = name;
    };

    this.getName = function () {
        return this.name;
    };
});

var FaqPage = BasePage.augment(function (base) {
    this.constructor = function (name, faq) {
        base.constructor.call(this, name);
        this.faq = faq;
    };

    this.getFaq = function () {
        return this.faq;
    };
});

然后你可以像往常一样使用它:

var faqPage = new FaqPage("Faq Page", "Faq");
var text = faqPage.getName() + " " + faqPage.getFaq();
$("body").text(text);

希望有帮助。

于 2013-05-19T16:29:03.407 回答