是否可以创建一个函数,其中[[prototype]]引用另一个函数

时间:2011-06-01 19:19:48

标签: javascript v8

我想创建函数对象(是的,所有函数都是对象),并对原型继承进行一些控制,也就是说,我想从一个函数继承另一个函数。

我可以创建具有原型继承的对象,并且知道设置函数的prototype属性作为构造函数来初始化对象的[[prototype]]属性。

但是,在创建函数时,我必须使用函数运算符或Function构造函数。我可以尝试调用Function.prototype,但是(1)不知道这是否可写,(2)这看起来很危险[仍然,我应该尝试这样做]。

btw:我只关心在node.JS中对V8这样做,所以如果有方法只适用于那个环境,那就可以接受了。

为了记录,我看到了这个: Is it possible to create a function with another prototype than Function.prototype?

3 个答案:

答案 0 :(得分:1)

在V8(以及IE以外的大多数其他浏览器/引擎)中,您可以通过设置 __prototype__ __proto__属性来更改对象的原型。如果将函数作为构造函数调用,则设置prototype属性将改为用于创建对象的原型。这不应该是你想要的。

Afaik目前没有标准的符合方式直接“子类化”一个函数(或数组)。只有Object.create,但没有Function.createArray.create

编辑: 我刚刚意识到函数对象没有__prototype__属性,并且更改/设置它不会将对象转换为函数。 我相信尽管我最近看过Brendan Eich(JavaScript的创建者)的一次演讲,他谈到了Object.create的函数和数组等价物。事实上,谷歌搜索“Function.create brendan eich”揭示了the following blog post by Eich,其中他谈到了他希望实现Function.create和Array.create。

编辑2:好的,我搞砸了。差不多。非标准属性当然是__proto__而不是__prototype__。设置__proto__适用于具有某些限制的函数,这些限制是:

  1. 为了能够呼叫aFunction,您必须使用实际功能对其进行初始化,例如:

    var aFunction = function () {};
    

    这很重要。调用函数不会访问原型链,因此如果您将aFunction定义为对象并只设置__proto__属性,则无法调用aFunction

    < / LI>
  2. 您现在可以将任何其他功能分配给aFunction.__proto__,如果在aFunction本身找不到该属性,则读取任何成员(包括方法)将正确委托给原型链。

  3. 调用aFunction()将始终调用最初在aFunction定义时声明的函数,并且永远不会调用aFunction的原型函数。所以函数的主体不受遗传约束。

  4. 很抱歉首先使用属性名称搞砸了。希望这对你有帮助。

答案 1 :(得分:1)

我想出了一个解决方案来解决我的需求。它不是不是跨浏览器,但可以跨浏览器使用。我最重要的用例是node.JS的模块。在这种情况下,设置__proto__的机制工作得很好,在这种情况下我可以在基函数对象上调用方法

f.method(args...);

并由“超级”功能中的代码执行。因为该方法是由方法调用模式调用的,所以“this”被设置为基本函数对象,因此即使该方法位于“超级”中,也会访问适当的属性。

现在对于浏览器内的情况:当我使用我的库客户端时,我提供了一个代理机制。唉,用于浏览器的代码必须以不同的方式编写。调用是:

f.proxy(methodName, args...);

基本功能对象中的代理方法是:

f.proxy = function (methodName) {
    var p = this.constructor.prototype;
    return p.proxy(this, methodName, arguments);
};

“超级”对象原型中的代理是:

proxy: function (instance, methodName) {
    var args = Array.prototype.splice.apply(arguments, [2]), 
        method = this[methodName];
    return (method) ? method.apply(instance, args) : undefined;
}

我可能应该将此命名为“前进”或其他一些,但“代理”已经足够好了。

也许这种机制可能对某人有用......

答案 2 :(得分:0)

我想我明白你要做什么。简而言之,没有办法真正做到这一点。您必须访问Function构造函数,对于函数表达式和定义(即使用'function'关键字的任何东西),我无法理解。您可以覆盖Function并始终使用new Function([args], string),但我怀疑您(或任何JS程序员)是否想要这样做。

您最好的选择可能是将您的函数表达式发送到另一个函数,该函数返回动态添加自定义方法的函数对象:

wrapFunc = function(f){
  f.customFunc = someCustomFunc;
  return f;
}

var myNewFunc = wrapFunc(
  function(){
    //do something
  }
);

myNewFunc.customFunc();