你能用JavaScript创建自定义原型的函数吗?

Stu*_*pid 12 javascript customization prototype function

首先,我并不想方法增加Function.prototype.这样做可以使它们适用于所有功能,而这不是我想要的.

在JavaScript中,您可以使用以下自定义原型创建对象:

function CustomObj() {}
CustomObj.prototype = {};
CustomObj.prototype.sayFoo = function () { return 'foo' };

var myCustomObj = new CustomObj(); //=> returns an object: {}
myCusomObj.sayFoo(); //=> 'foo'
Run Code Online (Sandbox Code Playgroud)

您还可以使用以下自定义原型创建类似于数组的对象:

function CustomArr() {}
CustomArr.prototype = [];
CustomObj.prototype.sayFoo = function () { return 'foo' };

var myCustomArr = new CustomArr(); //=> returns an ordered object: []
myCustomArr.sayFoo(); //=> 'foo'
Run Code Online (Sandbox Code Playgroud)

我想做的是使用某种构造函数以相同的方式创建一个具有自己的自定义原型的函数.但是,以下不起作用:

function CustomFn() {}
CustomFn.prototype = function () {};
CustomFn.prototype.sayFoo = function () { return 'foo' };

var myCustomFn = new CustomFn(); //=> PROBLEM! returns an object: {}
myCustomFn.sayFoo(); //=> 'foo'

// ^^ Here, the prototype was applied but the output was not a function.
myCustomFn(); //=> TypeError: object is not a function
Run Code Online (Sandbox Code Playgroud)

那么有什么方法可以完成我想要做的事情?

UPDATE

也许还有另外一种方式我可以问这个问题会让它更清晰一点.

关闭的想法存在问题:

function makeFn() {
  var output = function () { /* do some stuff */ };
  output.foo = function () { /* do some stuff */ };
  return output;
}
var specialFn = makeFn();
Run Code Online (Sandbox Code Playgroud)

从本质上讲,这种技术给了我想要的东西.但问题是每次调用makeFnoutput.foo都必须创建一个完全独立的函数来占用自己的内存.毛.所以我可以将该方法移出闭包:

var protoMethods = {
  "foo" : function () { /* do some stuff */ }
};
function makeFn() {
  var output = function () { /* do some stuff */ };
  for (var i in protoMethods) {
    Object.prototype.hasOwnProperty.call(protoMethods, i) &&
      (output[i] = protoMethods[i]);
  }
  return output;
}
var specialFn = makeFn();
Run Code Online (Sandbox Code Playgroud)

但是现在我每次调用时都必须手动进行迭代makeFn,这比我可以分配protoMethods为原型的效率低output.那么,有了这个新的更新,任何想法?

use*_*227 5

这确实是一件棘手的事情,如果语言设计得好的话,它应该会更复杂......

基本上,在当前版本中你无法干净地做到这一点。函数以外的对象不能被调用。

在未来的 Javascript 版本中,您可以使用可以定义“调用”处理程序的“代理”对象来完成此操作。但在我看来,它仍然过于复杂和做作。

另一种方法是让你的对象成为一个真正的函数,而不是一个自定义对象。然后尝试设置它的__proto__,它还不是标准的,但适用于大多数现代浏览器,除了 Opera 和 IE 8 或更低版本。也可以将其 constructor 属性设置为伪造instanceof检查...但这种黑客行为非常棘手,并且结果会因环境而异。

以下示例在我的 Firefox 上运行良好: http://jsfiddle.net/Q3422/2/

function MyFun() {
    if (!this || this==window) {
        return new MyFun();
    }

    var f = function() {
        return "thanks for calling!";
    }
    f.__proto__ = MyFun.prototype;
    f.constructor = MyFun;

    return f;
}

MyFun.prototype = {
    foo: function() {
        return "foo:" + this();
    },
    __proto__: Function.prototype
};

var f = new MyFun();
alert("proto method:"+f.foo()); // try our prototype methods
alert("function method:"+f.call()); // try standard function methods
alert("function call:"+f()); // try use as a function
alert('typeof:' + typeof f); // "function", not "object". No way around it in current js versions
alert('is MyFun:' + (f instanceof MyFun)); // true
alert('is Function:' + (f instanceof Function)); // true
Run Code Online (Sandbox Code Playgroud)

只是想补充一点,您不应该担心将函数“复制”到对象的每个实例。函数本身是一个对象,因此永远不会被真正复制,也不会被重新编译或任何东西。除了函数对象引用本身和任何闭包变量之外,它不会浪费内存。

迭代原型来复制它也不应该关心您,我想您不会有无数的方法。

因此,如果您需要支持原型不可设置的环境,并且您不担心原型可能会在创建某些对象后扩展并且它们可能无法接受更改,那么您自己的最后一个解决方案可能是最好的。


met*_*ngs 0

在开发V 库时我也尝试过。我想重写 Function 构造函数以强制执行构造函数的受限语法,我将其称为“类函数”(并且我有信心这样做)。

答案是否定的,使用 new 运算符只能创建新的“对象”,而不能创建新的“函数对象”。

但是,您可以将构造函数用作构造函数和函数!

var CustomFn = function () {
  if (this instanceof CustomFn) {
    // here we are 'new CustomFn()'
  }
  else {
    // here we are 'CustomFn()' or 'CustomFn.call()'
  }
};
Run Code Online (Sandbox Code Playgroud)

或者正如我认为更好的概念,首先执行该函数,然后让构造函数运行:

var CustomFn = function () {
  if (!(this instanceof CustomFn)) { // functioning
    // here we are 'CustomFn()' or 'CustomFn.call()'
    return new CustomFn(); // or return undefined or throw
  }

  // constructing
  // here we are 'new CustomFn()'

  // BaseCustomFn.call(this);
};
Run Code Online (Sandbox Code Playgroud)