Javascript 如何实现一个也有其他原型的函数

Javascript 如何实现一个也有其他原型的函数,javascript,function,Javascript,Function,我有一个FunctionArray对象,我想用它同时调用几个函数。基本上,您在这里看到的就是我到目前为止所看到的,但有一件事很好,就是只调用一个函数数组,如myFunctionArrayInstance()。有没有办法做到这一点,还是根本不可能 var FunctionArray = function(){ this.apply = function(){ var args = arguments; this.forEach(function(e,i){

我有一个FunctionArray对象,我想用它同时调用几个函数。基本上,您在这里看到的就是我到目前为止所看到的,但有一件事很好,就是只调用一个函数数组,如
myFunctionArrayInstance()
。有没有办法做到这一点,还是根本不可能

var FunctionArray =  function(){
    this.apply = function(){
        var args = arguments;
        this.forEach(function(e,i){
            e.apply(args);
        });
    }
    this.call = function(){
        var args = arguments;
        this.forEach(function(e,i){
            e.call(args);
        });
    }
    this.bind = function(){
        var args = arguments;
        var binds = [];
        this.forEach(function(e,i){
            binds.push(e.bind(args));
        });
        return function(){
            var args2 = arguments;
            binds.forEach(function(e,i){
                e.apply(args2);
            });
        };
    };

};
FunctionArray.prototype = [];
我就是这样用的

var initers = new FunctionArray();
initers.push(function(){/*something here*/});
initers.push(function(){/*something here*/});
initers();

你的结构看起来很有趣,但遗憾的是,如果你想让一个函数(而不是一个构造的对象)拥有一个定制的原型链,你需要使用非常昂贵的
对象.setPrototypeOf
,如果它产生了很多意想不到的结果,我也不会感到惊讶。您需要添加一个执行调用的方法

我认为,如果您不将数组放入原型中,而是在实例上拥有一个属性,该属性保存您的函数,并从您需要的数组中复制方法的包装版本,那么就更容易控制所有内容。我还添加了一个invoke并重新实现了length

那么基本上所有的东西都在原型中,除了你的函数数组。在初始定义之后,创建实例应该只需要很少的时间/内存

function FunctionArray() {
    this.fns = [];
}
FunctionArray.prototype = Object.create(null);
(function () {
    var i, arr = ['push', 'pop', 'shift', 'unshift', 'splice'];

    function addToProto(key, fn) {
        FunctionArray.prototype[key] = function () {
            return fn.apply(this.fns, arguments);
        };
    }

    for (i = 0; i < arr.length; ++i) {
        addToProto(arr[i], Array.prototype[arr[i]]);
    }

    Object.defineProperty(
        FunctionArray.prototype,
        'length',
        {
            get: function () {return this.fns.length;},
            set: function (x) {return this.fns.length = x;}
        }
    );

    FunctionArray.prototype.item = function (i) {
        return this.fns[i];
    };

    FunctionArray.prototype.invoke = function () {
        var i;
        for (i = 0; i < this.fns.length; ++i) {
            this.fns[i].apply(this, arguments);
        }
    };

    FunctionArray.prototype.call = function (ctx) {
        var i, args = arguments.slice(1);
        for (i = 0; i < this.fns.length; ++i) {
            this.fns[i].apply(ctx, args);
        }
    };

    FunctionArray.prototype.apply = function (ctx, args) {
        var i;
        for (i = 0; i < this.fns.length; ++i) {
            this.fns[i].apply(ctx, args);
        }
    };

    FunctionArray.prototype.bind = function () {
        var i;
        for (i = 0; i < this.fns.length; ++i) {
            this.fns[i] = Function.prototype.bind.apply(this.fns[i], arguments);
        }
    };
}());

然而, 这是可能的,但强烈不建议使用

现在

这是一个很酷的构造:)唉,如果构造的对象是数组的后代,它将不可调用。另一方面,为什么不将其设置为函数构造函数(这将使实例可调用),并使用类似于数组的机制来扩展此实例,以便在其中存储和检索函数

我在想:

(function(){ 'use strict';
function makeFunctionArray(){
    var functionArray = function(){
        functionArray.functions.forEach(function(f){
            f();
        });
    }

    functionArray.functions = [];
    functionArray.push=function(fnToAdd){
        functionArray.functions.push(fnToAdd);
    }
    functionArray.pop=function(){
        return functionArray.functions.pop();
    }
    //and so on... you can add any array functionality you need
    //(maybe even bracket notation with some fiddling?)

    return functionArray;
}

//using it:
var fa = makeFunctionArray();
typeof fa; //'function'
fa.push(function(){console.log(123);});
fa.push(function(){console.log(456);});
fa(); //-> outputs '123' then '456'
})();

编辑:根据格伦迪的建议清理代码。

您能提供示例如何使用它和示例输入输出吗?@Grundy,好的,我添加了一个示例。您确定需要创建类似对象的函数而不是简单使用的函数吗?嗯,我想将函数和数组结合起来。
var self=this;self=function(){
这里您重新分配了
self
,所以在它没有引用
这个
之后,您是对的,那一行是多余的。(我粘贴代码太匆忙了,它有一些不需要的行和调试日志)如果删除
var self=this;
nothingchanges@Grundy,如果我去掉这条线,self就可以在全球范围内使用:-p但这条线并不是整件事的重点。(整个自我/这个恶作剧只是我懒散的一部分,为了避免处理这个变化,当我开始键入这个答案时,我不认为这是没有必要的-我会编辑一点代码。)但我的意思是,你不使用
这个
只是好奇,什么是调用?理想情况下需要
fa('baz'))
而不是使用
invoke
:-)@Grundy如果这样做,您将失去原型的所有好处:(@PaulS.,但如果我们将其添加到函数的原型中会怎么样?@Grundy所有函数都继承自
函数.prototype
。唯一不使用的方法是使用
对象.setPrototypeOf
,这不是一个好主意,因为解释器无法预料到这一点,尤其是函数,
对象.setProto>typeOf(foo,Object.create(Function.prototype));
function FunctionArray() {
    var foo = function () {
        return foo.invoke.apply(foo, arguments);
    };
    Object.setPrototypeOf(foo, FunctionArray.prototype);
    foo.fns = [];
    return foo;
}
FunctionArray.prototype = Object.create(Function.prototype);
// continue from here as above
var fa = new FunctionArray();
fa.push(function (fizz) {console.log(this, fizz)});
fa.push(function (buzz) {console.log(this, buzz)});
fa.bind({'foo': 'bar'});
fa.length; // 2
fa('baz'); // logs {foo: "bar"} "baz" twice
(function(){ 'use strict';
function makeFunctionArray(){
    var functionArray = function(){
        functionArray.functions.forEach(function(f){
            f();
        });
    }

    functionArray.functions = [];
    functionArray.push=function(fnToAdd){
        functionArray.functions.push(fnToAdd);
    }
    functionArray.pop=function(){
        return functionArray.functions.pop();
    }
    //and so on... you can add any array functionality you need
    //(maybe even bracket notation with some fiddling?)

    return functionArray;
}

//using it:
var fa = makeFunctionArray();
typeof fa; //'function'
fa.push(function(){console.log(123);});
fa.push(function(){console.log(456);});
fa(); //-> outputs '123' then '456'
})();