我可以在Javascript中"扩展"一个闭包定义的"类"吗?

Jam*_*sen 15 javascript inheritance closures scoping

我有一个Javascript"类"定义如下:

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

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

new Welcomer('Sue').sayHi();
Run Code Online (Sandbox Code Playgroud)

有没有办法以Welcomer这样的方式"子类化" 我可以重新定义公共方法并可以访问私有方法和变量?以下内容将允许我访问公共方法,但不允许访问私有方法:

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();
Run Code Online (Sandbox Code Playgroud)

gna*_*arf 9

你的问题的简单答案是否定的.

你不能做任何事情来获取对那些var定义的东西的访问权限,除非你的函数在同一范围内,或者你以某种方式"公开"信息(通过返回或设置它this).

如果您有权编辑原始函数,则可以通过这样的方式重写事物,即这些函数可以"传递"到扩展函数中,这可以改变对象的"受保护"范围.以下代码应该很好地了解我提出的建议.

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();
Run Code Online (Sandbox Code Playgroud)


BGe*_*sen 8

这种"类"模式不是"类"模式,它被称为模块模式.它返回一个与创建它的函数没有关系的对象,除了它的私有变量的可用性.返回的对象不是创建它的函数的实例.

当你调用'new Class()'时,它会创建该函数的一个实例,但它也会返回另一个对象.任何进一步的操作实际上是返回的对象而不是实例.

为了使用继承,你真的需要正确使用原型继承,我建议你阅读:

进一步阅读:

很抱歉给您留下阅读材料,但在我看来,您正在探索各种可能性.这些文章将对此事进行更深入的了解.

一旦你对这个问题有了更多的了解,你很可能会完全忽略私人成员并使用_前缀,并像其他人一样使其成为公共成员;)这只是更容易,私人成员无论如何都是毫无意义的.