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

Javascript inheritance: overriding functionality with module pattern and $.extend

本文关键字:extend 覆盖 功能 模式 继承 模块 Javascript      更新时间:2023-09-26

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

// 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将被调用,"this"指向Child上下文。然而,A的上下文不是Child,而是全局(窗口)上下文。A的重写行为也不会被调用。

我必须使用模块模式(没有原型继承),并覆盖"超类"行为。

有没有人能让我知道我如何"保留"上下文,以确保被覆盖的行为被调用。

提前谢谢你,安德烈。

edit #1:我必须使用模块(并希望在重写行为时尽可能少地更改"父")

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

edit #3:似乎问题标题和问题是不同的,可能会误导:处理和回答的问题是真正的核心问题是关于javascript在(揭示)模块模式的上下文中重写(如其中一个答案所示)。范围的变化(确实发生了)被错误地认为是真正的问题。我要把它从标题中去掉。这样做是为了让其他人从下面的答案中受益。这里有一个范围变化,但在当前的代码设计和我的调用场景中,这可能是正常的。在这个问题中忽略这一方面

当你定义你的模块

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

通过在闭包中定义A和B,使用对"public"成员的直接闭包引用,然后将对象文字传递给$.extend,隐式地使用了揭示模块模式。揭示模块模式是基本模块模式的反模式变体,因为该变体无法获取覆盖。如果您想获取覆盖,一般的经验法则是尽可能多地使用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();
})();

我重写了你的代码如下,不确定这是否是你正在寻找的:

// 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 

可以使用bind函数

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

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