开发者

JavaScript inheritance without the 'new' keyword

I'm used to using this pattern all over my code, and I like it:

var UserWidget = (function(){
    var url = "/users",
        tmpl = "#users li", $tmpl;

    function load() {
        $tmpl = $(tmpl);
        $.getJSON(url, function(json){
            $.each(json, function(i, v) {
          开发者_C百科      appendUser(v);            
            });
        });
    }

    ...
    return {
        load: load
    };
})();

However, I have many "widget" objects. "ProfileWidget", "PlayerWidget" etc etc. and there's certain actions that each widget share. So ideally, if we're thinking object-orientally, I want each widget object to inherit some methods from a main "Widget" class.

How can I do this without changing this lovely pattern I've been using?

To be more clear I'd like to be able to do something like this:

var Widget = (function() {
    function init() {
        console.log("wow yeah");
    }
})();

// have UserWidget inherit somehow the Widget stuff
var UserWidget = (function() { ...

UserWidget.init(); // -> "wow yeah"


Keep in mind these solutions are not what I'd typically reccomend and they are just to satisfy the question.

What about closing over everything so that its accessible from your "sub classes" (demo)

var Widget = (function () {

    var init = function () {
        console.log("wow yeah");
    };

    var User = (function () {

        var load = function () {
            init();
        };

        return {
            'load': load
        };
    } ());

    return { 'User': User };
} ());

// Usage: This loads a user and calls init on the "base"
Widget.User.load();

Another way (demo) that you might like is to just use proper inheritance, but within the closure and then return one and only one instance of that new function. This way lets you keep User and whatever else an object

// Closing around widget is completely unneccesarry, but 
//    done here in case you want closures and in case you 
//    dont want another instance of widget
var Widget = (function () {

    // definition that we'll end up assigning to Widget
    function widget() {
           console.log("base ctor");
    }

    // sample method
    widget.prototype.init = function () {
        console.log("wow yeah");
    };

    // put widget in Widget
    return widget;
} ());

var User = (function () {

    function user() { }
    user.prototype = new Widget();

    // TODO: put your User methods into user.prototype

    return new user();
} ());

var Player = (function () {

    function player() { }
    player.prototype = new Widget();

    // TODO: put your Player methods into player.prototype

    return new player();

} ());

User.init();
Player.init();


I decided to use Crockford's object:

// function from Douglas Crockford, comments from me
function object(o) {
    // define a new function
    function F() {}
    // set the prototype to be the object we want to inherit 
    F.prototype = o;
    // return a new instance of that function, copying the prototype and allowing us to change it without worrying about modifying the initial object
    return new F();
}

// Usage:
var Widget = (function() {
    function init() {
        console.log("wow yeah");
    }
    return {
        init: init 
    };
})();

var UserWidget = (function() {
    var self = object(Widget); // inherit Widget
    function priv() {}
    self.pub = "boom";
    ...

    return self;
})();

UserWidget.init() // -> "wow yeah"

This works great for me and I like it!


You could use Object.create(obj), which I believe is what you're looking for.


Without using new, you'll have to use the __proto__ property rather than prototype, so this won't work in all browsers.

var Widget = {
    init: function () {
        console.log("wow yeah");
    }
};

var UserWidget = (function(){
    var url = "/users",
        tmpl = "#users li",
        $tmpl;

    function load() {
        $tmpl = $(tmpl);
        $.getJSON(url, function(json){
            $.each(json, function(i, v) {
                appendUser(v);            
            });
        });
    }

    return {
        load: load
    };
})();

UserWidget.__proto__ = Widget;

UserWidget.init();

Demo: http://jsfiddle.net/mattball/4Xfng/


Here's a simple example of prototyping in JS... For more detail on this topic read "JavaScript: The Good Parts"

// widget definition
var Widget = {
    init: function () {
        alert('wow yeah!');
    }
};
// user widget definition
var UserWidget = function () { };
UserWidget.prototype = Widget;
UserWidget.prototype.load = function () { alert('your code goes here'); }

// user widget instance
var uw = new UserWidget();
uw.init(); // wow yeah!
uw.load(); // your code goes here

Hope this helps!

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜