Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Extending the function prototype

I'm looking to be able to extend the function prototype in javascript (that is to say, add a function to all functions). The purpose is to convert it into a format for exchange between another language (namely ruby, which can only communicate through strings [in this particular setting]). I've already got a system so I can pass around other types by defining a to_js method on ruby objects and a to_ruby method on javascript objects, like so

Number.prototype.to_ruby = function () { return this.toString(); }

This is working for everything else I want it to, but not for functions. I can get it to work in chrome by doing the following:

_empty = function() {};
_empty.__proto__.to_ruby = function () {
    return 'JSFunction.new(' + this.toString().to_ruby() + ')';
};

But this does not work in IE (which is a requirement of the system).

I know I have an object somewhere keeping a track of functions by an ID or similar, but I can't guarantee that they will be used with the same instance that created them.

All else failing I could just write a function to special case deal with it (ie, isFunction(instance) ? fn_to_ruby(instance) : instance.to_ruby(), but I'd rather keep this model if possible.

like image 486
DanielB Avatar asked May 10 '12 06:05

DanielB


People also ask

Can you extend a function in JavaScript?

extend() Function. The _. extend() function is used to create a copy of all of the properties of the source objects over the destination object and return the destination object.

How do you write a prototype function?

A function prototype begins with the keyword function, then lists the function name, its parameters (if any), and return value (if any). The prototype includes no executable code. You can use function prototypes in the following situations: When defining an ExternalType (see ExternalType part).

What is the prototype of a function in JavaScript?

A function's prototype property, by default, is a plain object with one property: constructor , which is a reference to the function itself. The constructor property is writable, non-enumerable, and configurable.


2 Answers

As Slace said, you can add the method to all Objects by adding it to Object.prototype, but that isn't really kosher as it may affect badly written for..in loops.

You can add it just to functions via Function.prototype:

Function.prototype.to_ruby = function() {
  return this.toString();
}

However there is a general rule that you shouldn't modify built-in objects, mostly because you never know when it will come back to haunt you (e.g. a new version of ECMAScript implements a property with the same name). Perhaps you are better off to write a single toRuby function:

function toRuby(obj) {
  return obj.toString();
}

but you can also also use the + operator to concatenate with a string to call the toString method implicitly:

'' + obj; // returns obj.toString()

which will return exactly the same result as both the above. Your choice.

like image 100
RobG Avatar answered Oct 17 '22 10:10

RobG


__proto__ is not a standard property. Try this approach:

(function(){}).constructor.prototype.to_ruby = function(){
    return 'JSFunction.new(' + this.toString().to_ruby() + ')';
};
like image 22
Eineki Avatar answered Oct 17 '22 11:10

Eineki