您可以创建在JavaScript中的自定义函数的原型?(Can you create functio

2019-09-03 19:59发布

首先,我不想方法添加到Function.prototype 。 这样做会令他们可用于所有功能,这不是我要找的。

在JavaScript中,你可以创建这样的自定义原型对象:

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

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

您也可以创建这样的定制原型阵列状物体:

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

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

我想要做的是使用某种类型的构造函数来创建一个函数以同样的方式自己的定制样机。 但是,以下不工作:

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

那么,有没有办法来完成我想要做什么?

UPDATE

也许有另一种方式我可以问这个问题,将使其更清晰一点。

有一个封闭的观念问题:

function makeFn() {
  var output = function () { /* do some stuff */ };
  output.foo = function () { /* do some stuff */ };
  return output;
}
var specialFn = makeFn();

从本质上讲,这种技术给我我想要的。 然而,问题是,每次我打电话的时间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();

但现在我有我每次通话时间做手工迭代makeFn这将是比如果我可以分配效率较低protoMethods为原型output 。 所以,用这种新的更新,任何想法?

Answer 1:

这是一个棘手的事情的确,复杂得多,它应该是如果语言设计得很好...

基本上,你就不能在目前的版本中做干净。 比其他的功能对象无法调用。

在未来的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

只是想补充一点,你不应该担心“复制”功能,你的对象的每个实例。 函数本身是一个对象,所以从来没有真正被复制,也不是重新编译或任何东西。 它不浪费内存,除了函数对象引用本身和任何闭包变量。

遍历原型复制它不应该关心你听,我想你不会有一个极大的方法。

所以自己最后的解决方案可能是最好的,如果你需要支持这里proto是不可设置的环境中,你不担心早已见怪不怪创建了一些对象后您的原型可能会延长,他们可能不拿起变化。



Answer 2:

你是在什么样的继承在JavaScript是所有的心脏。 是的,因为原型的对象,你要CustomFn的原型设置为一个对象,而不是一个功能。

但是,对象可以来自另一个功能:

function ParentFn() {}
function CustomFn() {}
CustomFn.prototype = Object.create(ParentFn.prototype);
CustomFn.prototype.sayFoo = fun ...

如果你没有ES5或填充工具:

CustomFn.prototype = (function() {
                          function F(){}
                          F.prototype = ParentFn.prototype;
                          return new F();
                      }());

有些人可能会告诉你,只是做以下,但上述方式更好:

CustomFn.prototype = new ParentFn();


Answer 3:

我试过了太上工作时v磁带库 。 我想重写功能构造执行的构造函数有严格语法,那我打电话“类函数”(我坚信这样做)。

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

然而,你可以使用一个构造函数既作为构造和功能!

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

还是因为我相信是更好的概念,做功能排在首位,然后让构造走:

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);
};


文章来源: Can you create functions with custom prototypes in JavaScript?