Javascript继承:使用模块模式和$ .extend覆盖功能

时间:2014-06-20 11:48:49

标签: javascript jquery inheritance scope

我有以下情况,我在其中扩展父类并覆盖行为。但是,不会调用被覆盖的行为。

// parent scope definition
(function ($) {

 $.extend(true, window, {
  Demo: {
    Parent: Parent
  }
 });

 function Parent() {
  function A() {
    //do something
  }
  function B() {
    //do something else
    A();
  }
  // public api
  $.extend(this,{ "A":A, "B":B });
  }
})(jQuery);

// child scope definition
(function ($,parent) {

 $.extend(true, window, {
  Demo: {
    Child: Child
  }
 });

 function Child() {
  // inherit all from parent
  parent.apply(child,arguments);
  this.A = function () {
    // override parent behavior
  }
  this.B();
 }
})(jQuery,Parent);

//...somewhere else, in another scope call: var kid = new Child();
<html>
  <script>
    var kid = new Child();
  </script>
</html>

创建一个新的Child对象时,将调用B,使用&#34;这个&#34;指向Child上下文。但是,A的上下文不是Child,而是全局(窗口)上下文。 A的重写行为也不会被调用。

我必须使用模块模式(没有原型继承),并且还要覆盖&#34;超类&#34;行为。

有人可以让我知道我可以如何保存&#34;上下文,以确保调用被覆盖的行为。

提前谢谢你, 安德烈

编辑#1 :我必须使用模块(希望尽可能少地改变&#34; Parent&#34;尽可能覆盖行为)

编辑#2 :为了更加清晰,感谢下面提供的答案,我必须使用&#34;揭示模块模式&#34;对于Parent模块/对象,并在Child中扩展/覆盖其行为。

编辑#3 :似乎问题标题和问题是不同的,可能会产生误导:处理和回答的问题是真正的核心问题,关于javascript覆盖在上下文中(揭示)模块模式(如其中一个答案所示)。范围变化(确实发生)被错误地视为真正的问题。我正在删除它的标题提及。进行更正,以便其他人可以从下面的答案中受益。有一个范围更改,但这在当前代码设计和我的调用方案中可能是正常的。在这个问题中忽略这个方面(上下文)。

3 个答案:

答案 0 :(得分:1)

我已按如下方式重写您的代码,不确定这是否是您要找的:

// No need of IEFE
function Parent() {
  this.A=function A () {
    console.log("Executing A");
  }
  this.B= function B () {
    console.log("Executing B");
    this.A();
  }

};

//again, no need of IEFE, just declaring    
function Child() {
  // inherit all from parent
  Parent.apply(this);
  this.A = function () {
    console.log("Executing the new A");
  }
  this.B();
};

var c=new Child();
console.log("Done");

控制台显示:

Executing B
Executing the new A
Done 

答案 1 :(得分:1)

定义模块时

  $.extend(this,{ "A":A, "B":B });

通过在闭包中定义A和B,使用对“public”成员的直接闭包引用,然后将对象文字传递给$.extend,隐式使用Revealing Module Pattern。揭示模块模式是基本模块模式的反模式变体,因为this variant is unable to pick up overrides。如果您想要获取覆盖,一般的经验法则是尽可能使用this

在适当的情况下重写您的示例以使用this,以下应该可以解决问题:

(function Parent() {
  function A() {
    //do something
  }
  function B() {
    //use this!
    this.A();
  }
  // public api
  $.extend(this,{ "A":A, "B":B });
})();

(function Child() {
  // inherit all from parent
  Parent.apply(child,arguments);
  this.A = function () {
    // override parent behavior
  }
  this.B();
})();

答案 2 :(得分:0)

您可以使用绑定功能

var foo = function () {
// override parent behavior
}
this.A = foo.bind(child);

在上面的代码中,bind将返回一个基于foo的新函数对象,并将此set设置为child