最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

inheritance - Can I "extend" a closure-defined "class" in Javascript? - Stack Overflow

programmeradmin2浏览0评论

I have a Javascript "class" defined like so:

var Welcomer = function(name) {
  var pName = name;
  var pMessage = function() {
    return "Hi, " + pName + "!";
  };

  return {
    sayHi: function() {
      alert(pMessage());
    }
  };
};

new Welcomer('Sue').sayHi();

Is there a way to "subclass" Welcomer in such a way that I can redefine the public methods and have access to the private methods and variables? The following will give me access to the public methods, but not to the private ones:

var UnhappyWelcomer = function(name) {
  var pSadMessage = function() {
    // won't work, b/c I don't have access to pMessage
    return pMessage() + " Miserable day, innit?";
  };

  return {
    sayHi: function() {
      alert(pSadMessage());
    }
  };
};
UnhappyWelcomer.prototype = Welcomer(); // failed attempt at inheritance

new UnhappyWelcomer().sayHi();

I have a Javascript "class" defined like so:

var Welcomer = function(name) {
  var pName = name;
  var pMessage = function() {
    return "Hi, " + pName + "!";
  };

  return {
    sayHi: function() {
      alert(pMessage());
    }
  };
};

new Welcomer('Sue').sayHi();

Is there a way to "subclass" Welcomer in such a way that I can redefine the public methods and have access to the private methods and variables? The following will give me access to the public methods, but not to the private ones:

var UnhappyWelcomer = function(name) {
  var pSadMessage = function() {
    // won't work, b/c I don't have access to pMessage
    return pMessage() + " Miserable day, innit?";
  };

  return {
    sayHi: function() {
      alert(pSadMessage());
    }
  };
};
UnhappyWelcomer.prototype = Welcomer(); // failed attempt at inheritance

new UnhappyWelcomer().sayHi();
Share Improve this question edited Aug 24, 2010 at 21:32 James A. Rosen asked Aug 24, 2010 at 21:27 James A. RosenJames A. Rosen 65.2k62 gold badges184 silver badges263 bronze badges 2
  • 1 You might want to have a read over this article. – Matt Ball Commented Aug 24, 2010 at 21:35
  • Bookmarking that article. Thx – MK_Dev Commented Aug 24, 2010 at 21:39
Add a comment  | 

3 Answers 3

Reset to default 10

The simple answer to your question is No.

You can't do anything to gain access to those var defined things, unless your function is in the same scope, or you somehow 'make public' the information (by returning it, or setting it on this).

If you have access to edit the original function though, you could rewrite things in such a way that those functions could be "passed" into an extending function, which can alter the "protected" scope of the object. The following code should give a good idea of what I am proposing.

var Welcomer = function(name) {
  var _protected = {
    name: name,
    message: function() {
      return "Hi, " + _protected.name + "!";
    }
  };

  return {
    extendWith: function(extender) {
      extender.call(this, _protected);
      return this;
    },
    sayHi: function() {
      alert(_protected.message());
    }
  };
};

var UnhappyWelcomer = function(name) {
  var self = Welcomer(name).extendWith(function(_protected) {
    _protected.sadMessage = function() {
       return _protected.message() + " Miserable day, innit?";
    };
    // extending the public while still having scope to _protected...
    this.sayHi = function() {
      alert(_protected.sadMessage());
    };
  });
  return self;
};

UnhappyWelcomer('bob').sayHi();

That "class" pattern is not a "class" pattern, it's known as a Module Pattern. It returns an object that has no ties to the function that created it other then availability of it's private variables. The returned object is NOT an instance of the function that created it.

When you call 'new Class()' it does create an instance of that function, but it also returns another object. Any further operations is actually on the returned object and not the instance.

In order to use inheritance, you really need to use prototypical inheritance properly, I suggest you read:

  • Prototypical Inheritance by Douglas Crockford
  • Private Members in JavaScript by Douglas Crockford
  • Prototypes and Inheritance in JavaScript by Scott Allen (note: proto is not standard)

Further reading:

  • Classical Inheritance in JavaScript http://javascript.crockford.com/inheritance.html

Sorry to leave you with reading material, but it seems to me you are exploring possibilities. These articles will give a deeper insight on the matter.

Once you know more on the matter, you will most likely ignore private members alltogether and use the _ prefix and just make it a public member like everyone else ;) It's just easier and private members are pointless anyways.

If you really need inheritance, there are some libraries out there that will help immensely. One option is trait.js, which may actually become a standard part of javascript at some point anyway. If that doesnt float your boat, libraries like jQuery and prototype have helpers for inheritance.

If you want to go with a minimal/from-scratch approach, I strongly suggest you use the prototype model for everything. You will see a large performance increase over the pattern you have in your examples.

To more directly address your question, no. You will have an easier time if you design your 'classes' so private functions aren't relied upon.

发布评论

评论列表(0)

  1. 暂无评论