Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
138 views
in Technique[技术] by (71.8m points)

javascript - Is it possible to create a function with another prototype than Function.prototype?

I am working on a parser combinator library in JavaScript. For that I want to create functions that can be called like any other functions, but also have member functions that can be called in turn to produce output based on the function they are attached to (e.g. combinators).

I can of course add members to functions like this:

//the functions I want to add additional members to
function hello(x) {
    return "Hello " + x;
}

function goodbye(x) {
    return "Goodbye " + x;
}

//The function I want as a member of the above functions.
//it creates another function based on the function it is 
//attached to.
function double() { 
    var that = this;
    return function(x) {
        return that(x) + ", " + that(x);
    };
}

//I can attach them manually to the function objects:
hello.double = double;
//calling hello.double()('Joe') results in => "Hello Joe, Hello Joe"
goodbye.double = double;
//calling goodbye.double()('Joe') results in => "Goodbye Joe, Goodbye Joe"

I could create a function that augments all my functions with a double member, but I would have to remember to call it every time I create a Hey, Sayonara, etc. function. Also my greeting functions would have all those members each, directly on the function object, for each instance. I would prefer to put them all in one prototype and make this the prototype of all my greeting functions. The following options don't work either:

  • replacing hello.__proto__ (nonstandard, won't work in all browsers)
  • modifiying Function.prototype directly (would add those members to all other functions as well, but they do not make sense there - I only want to call double on a set of my own functions)

Is it even possible to give a function object a custom prototype or am I stuck with modifying each function object I create?


Update: I changed the above example to be more similar to the actual problem I am working on. This is about modyfing function objects not normal objects. The final goal is to enable a comfortable syntax for parser combinators, e.g. (much simplified):

//parses one argument
var arg = …
//parses one function name
var name = …
//parses a function call, e.g. foo(x+y, "test", a*2)
var functionCall = name.then(elem("(")).then(arg.repSep(",")).then(")").into(process(…))

I want to be able to add members to a set of functions so, when these members are called, they return new functions based on the function on which they were called. This is to be used for parser combinators / monadic parsers.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Yes, you can, using setPrototypeOf.

See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/setPrototypeOf.

function prototype() { }
prototype.double = function() { console.log("double"); };

function myfunc() { }
Object.setPrototypeOf(myfunc, prototype);

myfunc.double();

This is essentially the standardized version of __proto__.

There is no other way to directly create a function with a prototype other than Function.prototype. Consider:

function makeFunc() {
    return function x() { };
}
function protofunc { }
protofunc.double = { }...
makeFunc.prototype = protofunc;
new makeFunc()

Unfortunately, by returning a function from the makeFunc constructor, rather than the default this, the makeFunc.prototype is not applied.

Or:

myFunc = Object.create(protofunc, ???);

Normally we think of using Object.create to create an object with a prototype, but in this case, there's no way to specify a function as being the object.

Bottom line: the only alternative is to set the prototype explicitly, which you can do either with __proto__, or setPrototypeOf. This is an ES6 feature. Normal browser support caveats apply. See http://kangax.github.io/compat-table/es6/.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...