理解Javascript中的类和继承 - 新模式

时间:2012-05-15 05:00:47

标签: javascript oop inheritance object

我正在为我正在构建的许多应用程序设计OOP继承模式。 Javascript有很多方法可以做到这一点,但我偶然发现了一个我非常喜欢的模式。但现在我正在努力解决类和实例分离的需要。

我有一个名为Root的基础对象。它有一个名为inherit的主要方法。要创建新对象,请使用

var Person = Root.inherit({
    name : "",
    height : 0,
    walk : function() {},
    talk : function() {}
});

然后创建一个“实例”,你会

var sally = Person.inherit({
    name : "sally",
    height : "5'6"
});

sally可以.talk(),她可以走路(),她有.name和.height 你可以用同样的方式培养更多的人。

如果你想使用构造函数

var Person = Root.inherit({
    _construct : function() {
        // do things when this object is inherited from
    },
    name : "",
    height : 0,
    walk : function() {},
    talk : function() {}
});

当代码首次在代码中定义时(单例使用此代码),它还具有init的能力

var Person = Root.inherit({
    _init : function() {
        // called at runtime, NOT called if an object is inherited from me
    },
    name : "",
    height : 0,
    walk : function() {},
    talk : function() {}
});

正如您所看到的,一切都使用.inhert()。没有类,也没有实例。一切都是事物的一个例子。到目前为止我发现的唯一真正的问题是没有“类型”的概念,但如果需要,你总是可以检查一个方法。此外,您无法保护“类”,因为如果开发人员意外更改了“类”,或者意图更改它,则可以在执行期间更改“类”。

所以我的问题是:javascript中是否需要明确地控制类结构和类实例的分离?将每个对象视为实例是否存在任何问题?

6 个答案:

答案 0 :(得分:4)

没有必要,因为Javascript是基于Prototypal的语言,意味着不涉及类。您只是创建对象的克隆。

http://en.wikipedia.org/wiki/Prototype-based_programming

就类型的概念而言,类型是对象。

关于这方面的更多信息的一个很好的阅读将是Stoyan Stefanov的Javascript模式他有几种不同的创作模式可以解决您的问题,包括从四人设计模式中实现设计模式的示例。 http://www.amazon.com/JavaScript-Patterns-Stoyan-Stefanov/dp/0596806752

答案 1 :(得分:2)

  

所以我的问题是:javascript中是否需要明确地控制类结构和类实例的分离?将每个对象视为实例是否存在任何问题?

不是真的,如果你对此感到满意,那很好。

更常见的JavaScript继承形式可以做同样的事情。你会经常看到像这样的结构严重为了简洁而减少):

function Base() {
}
Base.prototype.foo = function() {
};

function Derived() {
}
Derived.prototype = new Base();

...当然,new Base()也是您创建Base实例的方式。所以你的系统非常相似。

同样,上面是 sketch ,而不是一个完整的例子。首先,通常你会看到构造和初始化被分离出来,所以你不会真正看到Derived.prototype = new Base()与使用Base的{​​{1}}创建对象的东西一样实际上是在调用prototypeBase稍后会做的),但是你明白了。虽然该声明在某种程度上削弱了与系统的相似性,但我认为它根本不会破坏它。

在一天结束时,全部是关于对象(实例),它们可以直接使用(Derived),也可以通过向其他对象提供功能来间接使用(sally,{{1} })通过克隆或将它们设置为另一个对象的原型。

答案 2 :(得分:1)

Javascript的继承是原型的,这意味着所有对象都是一个实例。你实际上必须做额外的工作来获得经典继承。

答案 3 :(得分:1)

这就是我在javascript中工作的方式

// this is class
function person(){

    // data is member variable 
     this.name = null;
     this.id = null;

    //member functions 
     this.set_name = _set_name;
     this.get_name = _get_name;
     this.set_id = _set_id;
     this.get_id = _get_id;

 function _set_name(name){
    this.name = name;
 } 

 function _get_name(name){
    return this.name;
 }

     function _set_id(id){
    this.id = id;
 } 

 function _get_id(id){
    return this.id;
 }
}

// this is instance
var yogs = new person();

    yogs.set_id(13);
    yogs.set_name("yogs");
希望它可以提供帮助

答案 4 :(得分:0)

从一些基本对象开始...

// javascript prototypes - callback example - javascript objects

function myDummyObject () {
    that = this;
} // end function myDummyObject ()

// begin dummy object's prototype
myDummyObject.prototype = {
    that : this,

    // add a simple command to our dummy object and load it with a callback entry
    say : function () {
        var that = this;

        console.log('speaking:');
        that.cb.run("doSay");
    }
} // end myDummyObject proto        

用子原型扩展..

// here we addon the callback handler... universally self sufficient object
var cb = {
    that : this, // come to papa ( a link to parent object [ myDummyObject ] )

    jCallback : new Array(new Array()),     // initialize a javascript 2d array 
    jCallbackID : -1,                       // stores the last callback id

    add: function(targetFnc, newFunc) {
        var that = this;
        var whichID = that.jCallbackID++;

        // target, addon, active
        that.jCallback[that.jCallback.length] =  { 'targetFunc' : targetFnc,  'newFunc' : newFunc,  'active' : true, 'id': whichID };

        return whichID; // if we want to delete this later...      
    }, // end add

    run: function(targetFnc) {
        var that = this;

        for(i=0;i <= that.jCallback.length - 1;i++) // go through callback list
            if( that.jCallback[i]['targetFunc'] == targetFnc  && that.jCallback[i]['active'] == true )
                that.jCallback[i]['newFunc'](); // run callback.
    }, // end run

    remove: function (whichID) {
        var that = this;
        console.log('removing:' + whichID); 

        for(i=0;i <= that.jCallback.length - 1;i++) // go through callback list
            if( that.jCallback[i]['id'] == whichID  )
                that.jCallback[i]['newFunc'](); // run callback.
    } // end remove
}                                                               

// add the object to the dummy object...
myDummyObject.prototype.cb = cb;

示例:

var testing = new myDummyObject();

testing.cb.add('doSay', function () { console.log('test: 213123123'); } );

// test remove...
var testid = testing.cb.add('doSay', function () { console.log('test: 12sad31'); } );
testing.cb.remove(testid);

testing.cb.add('doSay', function () { console.log('test: asdascccc'); } );
testing.cb.add('doSay', function () { console.log('test: qweqwe'); } );
testing.cb.add('doSay', function () { console.log('test: d121d21'); } );
testing.cb.add('doSay', function () { console.log('test: wwww'); } );


testing.say();

答案 5 :(得分:0)

这似乎对我来说似乎最容易理解......只需创建一个继承类的新实例,然后遍历其变量和方法并将它们添加到主类。

var myPerson = new Person()

var myPerson.firstName = 'john';
var myPerson.lastName = 'smith';
var myPerson.jobTitle = 'Programmer';    

var Person = function(){

    //Use this to inherit classes 
    this._extendedClass = new Person_Job();
    for(var i in this._extendedClass){
        this[i] = this._extendedClass[i];
    }
    delete this._extendedClass;

    this.firstName = '';
    this.lastName = '';
}

var Person_Job = function() {

    this.jobTitle = '';

}