javascript类继承自Function类

dgr*_*sen 12 javascript inheritance function-object prototypal-inheritance

我喜欢在javascript中,我可以创建一个函数,然后向该函数添加更多的方法和属性

myInstance = function() {return 5}
myInstance.attr = 10
Run Code Online (Sandbox Code Playgroud)

我想创建一个类来生成这些对象.我假设我必须从Function基类继承.

换句话说,我想:

var myInstance = new myFunctionClass()
var x = myInstance()
// x == 5
Run Code Online (Sandbox Code Playgroud)

但我不知道如何创建myFunctionClass.我尝试了以下,但它不起作用:

var myFunctionClass = function() {Function.call(this, "return 5")}
myFunctionClass.prototype = new Function()
myInstance = new myFunctionClass()
myInstance()
// I would hope this would return 5, but instead I get
// TypeError: Property 'myInstance' of object #<Object> is not a function
Run Code Online (Sandbox Code Playgroud)

我还试过这里找到的更复杂(也更合适?)的继承方法:如何在JavaScript中"正确"创建自定义对象?,没有更多的运气.我也尝试使用node.js中的util.inherits(myFunctionClass,Function).仍然没有运气

我已经筋疲力尽了谷歌,因此我觉得我必须遗漏一些基本或明显的东西.非常感谢帮助.

Ray*_*nos 14

你试图继承Function.这是一个正确的痛苦.我建议你做以下事情

实例

var Proto = Object.create(Function.prototype);
Object.extend(Proto, {
  constructor: function (d) {
    console.log("construct, argument : ", d);
    this.d = d; 
    // this is your constructor logic
  },
  call: function () {
    console.log("call", this.d);
    // this get's called when you invoke the "function" that is the instance
    return "from call";
  },
  method: function () {
    console.log("method");
    // some method
    return "return from method";
  },
  // some attr
  attr: 42
});
Run Code Online (Sandbox Code Playgroud)

您想要创建一个原型对象,它构成了"类"的基础.它有你的通用方法/属性.它还有一个在对象构造时调用的构造函数和一个在调用函数时调用的调用方法

var functionFactory = function (proto) {
  return function () {
    var f = function () {
      return f.call.apply(f, arguments);      
    };
    Object.keys(proto).forEach(function (key) {
      f[key] = proto[key];
    });
    f.constructor.apply(f, arguments);
    return f;
  }
}
Run Code Online (Sandbox Code Playgroud)

函数工厂获取原型对象并为其返回工厂.调用时返回的函数将为您提供一个从您的原型对象"继承"的新函数对象.

var protoFactory = functionFactory(proto);
var instance = protoFactory();
Run Code Online (Sandbox Code Playgroud)

在这里,您可以创建工厂,然后创建实例.

然而,这不是适当的原型OO.我们只是将原型的属性浅层复制到一个新对象中.因此对原型的更改不会反映回原始对象.

如果你想要真正的原型OO,那么你需要使用hack.

var f = function () {
  // your logic here
};
f.__proto__ = Proto;
Run Code Online (Sandbox Code Playgroud)

注意我们如何使用非标准弃用.__proto__ ,我们正在改变[[Prototype]]运行时被认为是邪恶的值.