首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Javascript继承和封装,高效完成

Javascript继承和封装,高效完成
EN

Stack Overflow用户
提问于 2015-02-17 09:23:19
回答 3查看 542关注 0票数 1

我来自C++ /Objective背景,我正在努力学习如何在Javascript中正确高效地再现继承和封装模式。我读了很多书(克罗克福德等)虽然有很多如何实现其中一个的例子,但我很难将它们结合在一起,而不引入重大的负面因素。

目前,我有这样的代码:

代码语言:javascript
复制
var BaseClass = (function() {

    function doThing() {
        console.log("[%s] Base-class's 'doThing'", this.name);
    }

    function reportThing() {
        console.log("[%s] Base-class's 'reportThing'", this.name);
    }

    return function(name) {
        var self = Object.create({});

        self.name = name;

        self.doThing = doThing;
        self.reportThing = reportThing;

        return self;
    }

}());

var SubClass = (function(base) {

    function extraThing() {
        console.log("[%s] Sub-class's 'extraThing'", this.name);
    }

    function doThing() {
        console.log("[%s] Sub-class's replacement 'doThing'", this.name);
    }    

    return function(name) {
        // Create an instance of the base object, passing our 'name' to it.
        var self = Object.create(base(name));    


        // We need to bind the new method to replace the old
        self.doThing = doThing;
        self.extraThing = extraThing;

        return self;
    }

}(BaseClass));

它主要做我想做的事:

代码语言:javascript
复制
// Create an instance of the base class and call it's two methods
var base = BaseClass("Bert");

base.doThing();         // "[Bert] Base-class's 'doThing'"
base.reportThing();     // "[Bert] Base-class's 'reportThing'"

var other = BaseClass("Fred");


// Create an instance of the sub-class and call it's three methods (two from the base, one of it's own)
var sub = SubClass("Alfred");

sub.doThing();          // "[Alfred] Sub-class's replacement 'doThing'"
sub.extraThing();       // "[Alfred] Sub-class's 'extraThing'"
sub.reportThing();      // "[Alfred] Base-class's 'reportThing'"

但是,(至少!)两个问题:

  • 我不相信原型链完好无损。如果我通过子类的一个实例替换原型中的方法,其他实例就不会看到它:
  • 不封装.name特性

我正在替换原型的实现,如下所示:

代码语言:javascript
复制
Object.getPrototypeOf(oneInstance).reportThing = function() { ... }
otherInstance.reportThing()    // Original version is still called

这也许不是一个重大的问题,但它使我怀疑我的理解。

但是,私有变量是我想要高效实现的东西。变量隐藏的模块模式在这里没有帮助,因为它会导致每个对象都存在函数定义。我可能错过了一种组合模式的方法,那么有没有一种在不重复函数的情况下实现私有变量的方法?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2015-02-17 12:52:04

这通常是我在JavaScript中处理继承和封装的方式。defclass函数用于创建一个不从任何其他类继承的新类,extend函数用于创建一个扩展另一个类的新类:

代码语言:javascript
复制
var base = new BaseClass("Bert");

base.doThing();     // "Bert BaseClass doThing"
base.reportThing(); // "Bert BaseClass reportThing"

var sub = new SubClass("Alfred");

sub.doThing();     // "Alfred SubClass replacement doThing"
sub.extraThing();  // "Alfred SubClass extraThing"
sub.reportThing(); // "Alfred BaseClass reportThing"

var other = new SubClass("Fred");

SubClass.prototype.reportThing = function () {
    console.log(this.name + " SubClass replacement reportThing");
};

other.reportThing(); // Fred SubClass replacement reportThing
代码语言:javascript
复制
<script>
function defclass(prototype) {
    var constructor = prototype.constructor;
    constructor.prototype = prototype;
    return constructor;
}

function extend(constructor, keys) {
    var prototype = Object.create(constructor.prototype);
    for (var key in keys) prototype[key] = keys[key];
    return defclass(prototype);
}

var BaseClass = defclass({
    constructor: function (name) {
        this.name = name;
    },
    doThing: function () {
        console.log(this.name + " BaseClass doThing");
    },
    reportThing: function () {
        console.log(this.name + " BaseClass reportThing");
    }
});

var SubClass = extend(BaseClass, {
    constructor: function (name) {
        BaseClass.call(this, name);
    },
    doThing: function () {
        console.log(this.name + " SubClass replacement doThing");
    },
    extraThing: function () {
        console.log(this.name + " SubClass extraThing");
    }
});
</script>

阅读以下答案,了解JavaScript中的继承是如何工作的:

用这种方式定义原型功能的缺点是什么?

解释了原型和构造器的区别。此外,它还展示了原型和类是如何同构的,以及如何在JavaScript中创建“类”。

希望这能有所帮助。

票数 1
EN

Stack Overflow用户

发布于 2015-02-17 12:36:38

简单的配方如下:

代码语言:javascript
复制
function BaseClass(someParams)
{
   // Setup the public properties, e.g.
   this.name = someParams.name;
}

BaseClass.prototype.someMethod = function(){
   // Do something with the public properties
}

现在继承是这样发生的。

代码语言:javascript
复制
function SubClass(someParams)
{ 
    // Reuse the base class constructor
    BaseClass.call(this, someParams);

    // Keep initializing stuff that wasn't initialized by the base class
    this.anotherProperty= someParams.anotherProperty;
}

// Copy the prototype from the BaseClass
SubClass.prototype = Object.create(BaseClass.prototype);
SubClass.prototype.constructor = SubClass;

// Start extending or overriding stuff
SubClass.prototype.someMethod = function(){

   // In case you still wanna have the side effects of the original method
   // This is opt-in code so it depends on your scenario.
   BaseClass.prototype.someMethod.apply(this, arguments);

   // Override the method here       
}

摘自:JavaScript

P.S. Object.create可能并不是所有旧浏览器都支持的,但是不要担心,这个链接中有一个多填充。对象/对象/创建

票数 1
EN

Stack Overflow用户

发布于 2015-02-17 11:28:18

如果要保留原型链,则必须重写并使用.prototype:示例: Main:

代码语言:javascript
复制
function BaseClass(){

}
BaseClass.prototype.doThing = function(){...}

SubClass:

代码语言:javascript
复制
function SubClass(){
}
SubClass.prototype= new BaseClass();
SubClass.prototype.extraThing = function(){};

现在,每当您更改extraThing或doThing时,就会到处替换它。name属性可以作为公共变量访问(它不是静态的)。

如果你想让它是静态的,你必须把它放在原型中。

如果你希望它是私有的,你应该让它在本地发挥作用:

代码语言:javascript
复制
function BaseClass(nameParam){
 var name = nameParam;
}

要创建一个对象,只需调用该函数:

代码语言:javascript
复制
var testObj = new BaseClass("test");
testObj.doThing();

如果您想将私有变量与可重写函数组合起来,您可能会找到您的回答这里。但是如果您能够重写访问私有变量的函数,那么它就不再是真正的私有变量了。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28558503

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档