简体   繁体   English

如何实现也具有其他原型的功能

[英]How to implement a function that also has a prototype of something else

I have a FunctionArray object which I want to use to call several functions at once. 我有一个FunctionArray对象,我想用来一次调用多个函数。 Basically what you see here is what I have so far, but one thing that would be nice is to just call a function array like myFunctionArrayInstance() . 基本上,您在这里看到的就是我到目前为止所拥有的,但是一件很不错的事情就是调用像myFunctionArrayInstance()这样的函数数组。 Is there a way to do that or is it just not possible? 有没有办法做到这一点?

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 = [];

And I use it like this. 我这样使用它。

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

Your structure looked interesting, but sadly if you want a Function (as opposed to a constructed Object ) to have a custom prototype chain you need to use the very costly Object.setPrototypeOf and I would not be surprised if it produced lots of unexpected results. 您的结构看起来很有趣,但是令人遗憾的是,如果您想要一个Function (而不是一个构造的Object )具有自定义原型链,则需要使用非常昂贵的Object.setPrototypeOf并且如果它产生很多意外的结果,我也不会感到惊讶。 You'll need to add a method which does the invocation. 您需要添加执行调用的方法。

I think it would be easier to keep control over everything if you don't put your Array in the prototype and instead have a property on the instance which holds your Functions and copy wrapped versions of the methods over from Array that you need. 我认为,如果不将Array放在原型中,而是在实例上拥有一个属性,该属性可以保存函数并从所需的Array复制方法的包装版本,那么对所有内容进行控制会更容易。 I also added an invoke and re-implemented length . 我还添加了一个invoke和re-implemented的length

Then basically everything is in the prototype except the Array of your functions. 然后, 除了函数数组 之外 ,基本上所有内容都在原型中。 After the initial definition creating instances should require very little time/memory. 在初始定义之后,创建实例应该只需要很少的时间/内存。

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

Now you can do something like 现在你可以做类似的事情

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.invoke('baz'); // logs {foo: "bar"} "baz" twice

However, 然而,

It is possible but strongly not reccomended, using Object.setPrototypeOf 使用Object.setPrototypeOf可能但强烈不建议使用

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

Now 现在

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

That's a cool construct :) Alas, if the constructed objects are descendants of array, it won't be callable. 这是一个很酷的构造:) las,如果构造的对象是array的后代,则将无法调用它。 On the other hand, why not make it a function constructor (which would make the instances callable), and augment this instance with array-like mechanisms for storing and retrieving the functions within? 另一方面,为什么不让它成为一个函数构造函数(这将使实例可调用),并使用存储和检索其中的函数的类似于数组的机制来扩展此实例呢?

I'm thinking: 我在想:

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

Edit: cleaned up code according to Grundy's suggestions. 编辑:根据Grundy的建议清理代码。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何通过更改其他颜色来指示已单击某些内容? - How to indicate that that something has been clicked by changing color of something else? 功能JavaScript:如何实现Function.prototype.not - Functional JavaScript: how to implement Function.prototype.not 如何在javascript中实现二维数组的原型函数? - How to implement prototype function with 2 dimensional array in javascript? 在js库中$ .something(object)如何也是$(“something”)(一个函数)? - in js libraries how can $.something (object) also be $(“something”) (a function)? 如何在不使用Apply的情况下实现Function.prototype.apply? - How to implement Function.prototype.apply without using apply? ELSE 语句中的函数也与 IF 语句一起执行,如何防止这种情况? - A function in ELSE statement is executed also with IF statement, how to prevent this? 我的函数参数有问题还是其他问题? - Is there something wrong with my function arguments or is it something else? 如何在不破坏其他东西的情况下修复“element.dispatchEvent is not a function”? - How to fix “element.dispatchEvent is not a function” without breaking something else? 如何保持onmouseover功能,直到将鼠标悬停在其他地方 - How to keep onmouseover function until mousing over something else 如何在调用函数或执行其他操作之前更改背景颜色 - How to change background color before calling a function or doing something else
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM