通过调用祖先函数继承JavaScript

时间:2013-09-01 12:11:45

标签: javascript node.js inheritance

我正在试验(对我来说)一种新型的继承。我想用一个参数调用继承的函数,该参数确定返回哪个继承者对象。

这是一个展示我的意思的例子:

function Localizor(type) {
  this.language = "English"
  this.endonym = "English"

  if (window[type]) {
    return new window[type]()
  }
}
Localizor.prototype.native = function native() {
  return "I speak " + this.endonym
}
Localizor.prototype.english = function () {
  return "I speak " + this.language
}


function French () {
  this.language = "French";  
  this.endonym = "français"
}
French.prototype = new Localizor()
French.prototype.native = function french() {
  return "Je parle " + this.endonym
}


function Thai () {
  this.language = "Thai";  
  this.endonym = "ไทย"
}
Thai.prototype = new Localizor()
Thai.prototype.native = function thai() {
  return "พูดภาษา" + this.endonym
}

如果我在没有参数(或参数无效)的情况下调用new Localizor(),我会得到一个简单的英文对象。如果我用“French”或“Thai”的参数调用它,我会得到一个对象,其中继承者会覆盖一些继承的方法,因此它会说法语或泰语。例如:

var thai = new Localizor("Thai")
var feedback = thai.language + " | " + thai.endonym + " | " + thai.english() + " | " + thai.native()  
console.log(feedback)

这为我提供了输出Thai | ไทย | I speak Thai | พูดภาษาไทย

我有三个问题:
1.这种类型的继承是否已在某处记录(是否有名称)? 这样工作有危险吗? 3.此示例检查是否存在window[type],这在浏览器中工作时很好。如果这是在node.js的模块中,是否有一种等效的方法来确定模块中是否存在函数?

编辑以响应Zero21xxx

这是我发现在模块中检测构造函数存在的一种方法,但对我来说它看起来很危险。它有什么风险?有哪些更好的方法?

function extend(Child, Parent) {
  function F() {}
  F.prototype = Parent.prototype
  Child.prototype = new F()
  //Child.prototype.constructor = Child
  Child.parent = Parent.prototype
}

function Localizor(type) {
  this.language = "English"
  this.endonym = "English"

  this.French = function français () {
    this.language = "French";  
    this.endonym = "français"
  }
  extend(this.French, this)
  this.French.prototype.native = function french() {
    return "Je parle " + this.endonym
  }

  this.Thai = function ไทย () {
    this.language = "Thai";  
    this.endonym = "ไทย"
  }
  extend(this.Thai, this)
  this.Thai.prototype.native = function thai() {
    return "พูดภาษา" + this.endonym
  }

  if (typeof this[type] === "function") {
   return new this[type]()
  }
}
Localizor.prototype.native = function native() {
  return "I speak " + this.endonym
}
Localizor.prototype.english = function () {
  return "I speak " + this.language
}

module.exports = Localizor

2 个答案:

答案 0 :(得分:3)

根据我的拙见,你应该为EnglishFrenchThai提供三个独立的构造函数,这些构造函数继承自一个公共构造函数(让我们称之为Locale)。它看起来如下:

function Locale(constructor, language, endonym, native) {
    this.constructor = constructor;
    this.language = language;
    this.endonym = endonym;

    this.native = function () {
        return native + this.endonym;
    };
}

Locale.prototype.english = function () {
    return "I speak " + this.language;
};

function English() {}
function French() {}
function Thai() {}

English.prototype = new Locale(English, "English", "English", "I speak ");
French.prototype = new Locale(French, "French", "français", "Je parle ");
Thai.prototype = new Locale(Thai, "Thai", "ไทย", "พูดภาษา");

这导致separation of concerns:每个构造函数只能完全按照它的目的。没有更多,没有更少。现在您可以创建localizer函数,如下所示:

function localizer(language) {
    switch (language) {
    case "French": return new French;
    case "Thai": return new Thai;
    default: return new English;
    }
}

因此,您只需致电localizer即可获得所需的Locale

答案 1 :(得分:0)

  1. 是的,这是人们经常试图以不同程度的成功实现的“伪经典”类型的继承。查看this
  2. 你现在拥有它的方式有点难读。您编写的代码表示创建了一个Localizor对象,但您将返回一个Thai对象。这可能很难追查错误。
  3. 是的,有办法检查这些事情,这实际上取决于你如何构建模块。
  4. 我的建议是稍微改写这个

    function Localizor(language, endonym) {
      this.language = language;
      this.endonym = endonym;
    }
    Localizor.prototype.native = function native() {
      return "I speak " + this.endonym;
    };
    Localizor.prototype.english = function () {
      return "I speak " + this.language;
    };
    
    
    function French (language, endonym) {
      Localizor.apply(this, arguments);
    }
    French.prototype = new Localizor();
    French.prototype.native = function french() {
      return "Je parle " + this.endonym;
    };
    
    
    function Thai (language, endonym) {
      Localizor.apply(this, arguments);
    }
    Thai.prototype = new Localizor();
    Thai.prototype.native = function thai() {
      return "พูดภาษา" + this.endonym;
    };
    

    这样,您可以调用正确的构造函数并返回相应的对象。您还可以调用“基类”构造函数并附加languageendonym属性,而无需复制和粘贴该代码。您也不需要检查类似于您当前正在执行的类型,因为您要声明它们希望它们如何运行。最后,如果你想,你可以让你的Localizor函数取第三个参数,那就是字符串“I Speak”或者其他什么,然后你不会需要多个对象。

    Here是一个你可以搞砸的游乐场。

    服务器或客户端,我认为这是一种更好的方法。