Does Javascript have something like Ruby's method_missing feature? - javascript

In Ruby I think you can call a method that hasn't been defined and yet capture the name of the method called and do processing of this method at runtime.
Can Javascript do the same kind of thing ?

method_missing does not fit well with JavaScript for the same reason it does not exist in Python: in both languages, methods are just attributes that happen to be functions; and objects often have public attributes that are not callable. Contrast with Ruby, where the public interface of an object is 100% methods.
What is needed in JavaScript is a hook to catch access to missing attributes, whether they are methods or not. Python has it: see the __getattr__ special method.
The __noSuchMethod__ proposal by Mozilla introduced yet another inconsistency in a language riddled with them.
The way forward for JavaScript is the Proxy mechanism (also in ECMAscript Harmony), which is closer to the Python protocol for customizing attribute access than to Ruby's method_missing.

The ruby feature that you are explaining is called "method_missing" http://rubylearning.com/satishtalim/ruby_method_missing.htm.
It's a brand new feature that is present only in some browsers like Firefox (in the spider monkey Javascript engine). In SpiderMonkey it's called "__noSuchMethod__" https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/NoSuchMethod
Please read this article from Yehuda Katz http://yehudakatz.com/2008/08/18/method_missing-in-javascript/ for more details about the upcoming implementation.

Not at the moment, no. There is a proposal for ECMAScript Harmony, called proxies, which implements a similar (actually, much more powerful) feature, but ECMAScript Harmony isn't out yet and probably won't be for a couple of years.

You can use the Proxy class.
var myObj = {
someAttr: 'foo'
};
var p = new Proxy(myObj, {
get: function (target, methodOrAttributeName) {
// target is the first argument passed into new Proxy, aka. target is myObj
// First give the target a chance to handle it
if (Object.keys(target).indexOf(methodOrAttributeName) !== -1) {
return target[methodOrAttributeName];
}
// If the target did not have the method/attribute return whatever we want
// Explicitly handle certain cases
if (methodOrAttributeName === 'specialPants') {
return 'trousers';
}
// return our generic method_missing function
return function () {
// Use the special "arguments" object to access a variable number arguments
return 'For show, myObj.someAttr="' + target.someAttr + '" and "'
+ methodOrAttributeName + '" called with: ['
+ Array.prototype.slice.call(arguments).join(',') + ']';
}
}
});
console.log(p.specialPants);
// outputs: trousers
console.log(p.unknownMethod('hi', 'bye', 'ok'));
// outputs:
// For show, myObj.someAttr="foo" and "unknownMethod" called with: [hi,bye,ok]
About
You would use p in place of myObj.
You should be careful with get because it intercepts all attribute requests of p. So, p.specialPants() would result in an error because specialPants returns a string and not a function.
What's really going on with unknownMethod is equivalent to the following:
var unk = p.unkownMethod;
unk('hi', 'bye', 'ok');
This works because functions are objects in javascript.
Bonus
If you know the number of arguments you expect, you can declare them as normal in the returned function.
eg:
...
get: function (target, name) {
return function(expectedArg1, expectedArg2) {
...

I've created a library for javascript that let you use method_missing in javascript: https://github.com/ramadis/unmiss
It uses ES6 Proxies to work. Here is an example using ES6 Class inheritance. However you can also use decorators to achieve the same results.
import { MethodMissingClass } from 'unmiss'
class Example extends MethodMissingClass {
methodMissing(name, ...args) {
console.log(`Method ${name} was called with arguments: ${args.join(' ')}`);
}
}
const instance = new Example;
instance.what('is', 'this');
> Method what was called with arguments: is this

No, there is no metaprogramming capability in javascript directly analogous to ruby's method_missing hook. The interpreter simply raises an Error which the calling code can catch but cannot be detected by the object being accessed. There are some answers here about defining functions at run time, but that's not the same thing. You can do lots of metaprogramming, changing specific instances of objects, defining functions, doing functional things like memoizing and decorators. But there's no dynamic metaprogramming of missing functions as there is in ruby or python.

I came to this question because I was looking for a way to fall through to another object if the method wasn't present on the first object. It's not quite as flexible as what your asking - for instance if a method is missing from both then it will fail.
I was thinking of doing this for a little library I've got that helps configure extjs objects in a way that also makes them more testable. I had seperate calls to actually get hold of the objects for interaction and thought this might be a nice way of sticking those calls together by effectively returning an augmented type
I can think of two ways of doing this:
Prototypes
You can do this using prototypes - as stuff falls through to the prototype if it isn't on the actual object. It seems like this wouldn't work if the set of functions you want drop through to use the this keyword - obviously your object wont know or care about stuff that the other one knows about.
If its all your own code and you aren't using this and constructors ... which is a good idea for lots of reasons then you can do it like this:
var makeHorse = function () {
var neigh = "neigh";
return {
doTheNoise: function () {
return neigh + " is all im saying"
},
setNeigh: function (newNoise) {
neigh = newNoise;
}
}
};
var createSomething = function (fallThrough) {
var constructor = function () {};
constructor.prototype = fallThrough;
var instance = new constructor();
instance.someMethod = function () {
console.log("aaaaa");
};
instance.callTheOther = function () {
var theNoise = instance.doTheNoise();
console.log(theNoise);
};
return instance;
};
var firstHorse = makeHorse();
var secondHorse = makeHorse();
secondHorse.setNeigh("mooo");
var firstWrapper = createSomething(firstHorse);
var secondWrapper = createSomething(secondHorse);
var nothingWrapper = createSomething();
firstWrapper.someMethod();
firstWrapper.callTheOther();
console.log(firstWrapper.doTheNoise());
secondWrapper.someMethod();
secondWrapper.callTheOther();
console.log(secondWrapper.doTheNoise());
nothingWrapper.someMethod();
//this call fails as we dont have this method on the fall through object (which is undefined)
console.log(nothingWrapper.doTheNoise());
This doesn't work for my use case as the extjs guys have not only mistakenly used 'this' they've also built a whole crazy classical inheritance type system on the principal of using prototypes and 'this'.
This is actually the first time I've used prototypes/constructors and I was slightly baffled that you can't just set the prototype - you also have to use a constructor. There is a magic field in objects (at least in firefox) call __proto which is basically the real prototype. it seems the actual prototype field is only used at construction time... how confusing!
Copying methods
This method is probably more expensive but seems more elegant to me and will also work on code that is using this (eg so you can use it to wrap library objects). It will also work on stuff written using the functional/closure style aswell - I've just illustrated it with this/constructors to show it works with stuff like that.
Here's the mods:
//this is now a constructor
var MakeHorse = function () {
this.neigh = "neigh";
};
MakeHorse.prototype.doTheNoise = function () {
return this.neigh + " is all im saying"
};
MakeHorse.prototype.setNeigh = function (newNoise) {
this.neigh = newNoise;
};
var createSomething = function (fallThrough) {
var instance = {
someMethod : function () {
console.log("aaaaa");
},
callTheOther : function () {
//note this has had to change to directly call the fallThrough object
var theNoise = fallThrough.doTheNoise();
console.log(theNoise);
}
};
//copy stuff over but not if it already exists
for (var propertyName in fallThrough)
if (!instance.hasOwnProperty(propertyName))
instance[propertyName] = fallThrough[propertyName];
return instance;
};
var firstHorse = new MakeHorse();
var secondHorse = new MakeHorse();
secondHorse.setNeigh("mooo");
var firstWrapper = createSomething(firstHorse);
var secondWrapper = createSomething(secondHorse);
var nothingWrapper = createSomething();
firstWrapper.someMethod();
firstWrapper.callTheOther();
console.log(firstWrapper.doTheNoise());
secondWrapper.someMethod();
secondWrapper.callTheOther();
console.log(secondWrapper.doTheNoise());
nothingWrapper.someMethod();
//this call fails as we dont have this method on the fall through object (which is undefined)
console.log(nothingWrapper.doTheNoise());
I was actually anticipating having to use bind in there somewhere but it appears not to be necessary.

Not to my knowledge, but you can simulate it by initializing the function to null at first and then replacing the implementation later.
var foo = null;
var bar = function() { alert(foo()); } // Appear to use foo before definition
// ...
foo = function() { return "ABC"; } /* Define the function */
bar(); /* Alert box pops up with "ABC" */
This trick is similar to a C# trick for implementing recursive lambdas, as described here.
The only downside is that if you do use foo before it's defined, you'll get an error for trying to call null as though it were a function, rather than a more descriptive error message. But you would expect to get some error message for using a function before it's defined.

Related

How to detect function creation js

I am trying to detect when a function is created, preferable through a constructor. Functions are a type of object, right? So it makes sense that when you create a new one, it calls a constructor. Is there a way to override this, for example, something like this
var old = Function.constructor;
Function.constructor = () => {
alert('new function created!');
old();
};
function asdf() {}
var k = new Function();
If this is not possible, is there a way to get all currently defined functions? I am trying to trigger a piece of code on each function run.
You can't detect function creation.
Functions are a type of object, right?
Yes.
So it makes sense that when you create a new one, it calls a constructor.
No. Or - maybe, but that constructor is internal. Just like the construction of objects from array literals, object literals, regex literals, definition of a function directly creates a native object.
Is there a way to override this?
No. You'd need to hook into the JS engine itself for that.
If this is not possible, is there a way to get all currently defined functions?
No. At best, you could try the debugging API of the JS engine and get a heap snapshot, that should contain all function objects.
I am trying to trigger a piece of code on each function run.
Let me guess, that piece of code is a function itself?
Was able to get a semi-working attempt at this. It reads only global functions but it can add code to both the front and beginning of the function. Any tips on how to improve this, as I use classes a lot when I code?
Thanks to Barmar for the idea of looping through window properties, but since you can't access local functions and class functions, this may be the closest way to do this
<script>
function prepend(name) {
console.time(name);
}
function postpend(name) {
console.timeEnd(name);
}
var filter = ['prepend', 'postpend', 'caches'];
function laggyFunction() {
var l = 0;
while (l<1000) {l++}
}
var functions = [];
for (var property in window) {
try {
if (!filter.includes(property)) { // security error on accessing cache in stackoverflow editor along with maximum call stack size exceeded if prepend and postpend are included
if (typeof window[property] === 'function') {
window[property].original = window[property];
window[property].name = property;
window[property] = function() {
prepend(this.name);
console.log(this.original);
this.original.apply(null, arguments);
postpend(this.name);
}.bind(window[property]);
functions.push(property);
}
}
} catch(e) {
console.warn(`Couldn't access property: `+property+' | '+e);
}
}
document.write(functions); // functions the prepend and postpend are applied to
laggyFunction(); // test performance of the function
</script>

Constructor and prototypes in javascript

I'm reading a snippet of code that defines a constuctor
var Resource = function(data) {
angular.extend(this, data);
}
and then subsequently defines a method to it.
Resource.query = function(url) {
console.log(url);
}
Can I ask how this works? I know functions are objects as well, and is this the equivalent of the following? But if so, then what happens to the constructor function?
var data = {};
data.query = function(url) {
console.log(url);
}
Also, why wouldn't we simply define it on the prototype instead?
Resource.prototype.query = function(url) {
console.log(url);
}
http://jsfiddle.net/HPg6A/
You would define methods on the prototype only if they are meant to be called on specific instances. When methods are defined directly as constructor members, it's usually to mimic static methods.
Basically, when a method relates very closely to a class, but doesn't make much sense as an instance method, it can be implemented as a static method.
I think that you will agree with me that the second example makes more sense and if you do, you already understood the difference.
1-
var user = new User();
user.findUser('somequery').then(...);
2-
User.findUser('somequery').then(...);
I know functions are objects as well, and is this the equivalent of the following
There's nothing more to what you say. It's just like any other property on any other object.
Also, why wouldn't we simply define it on the prototype instead?
The difference is that each object created using the constructor would then have that method in their prototype chain. This isn't true for properties defined on the constructor itself.
That is:
var Resource = function() {}
Resource.one = function() {
console.log("one");
}
Resource.prototype.two = function() {
console.log("two");
}
var r = new Resource();
r.two(); // => "two"
r.one(); // => TypeError: r.one is not a function
And:
Resource.one(); // => "one"
Resource.two(); // => TypeError: Resource.two is not a function
You might call one a static method, but the language doesn't treat it differently than any other function (unlike methods defined using, say, static in Java).

Overriding methods using Javascript module pattern

I've got a browser addon I've been maintaining for 5 years, and I'd like to share some common code between the Firefox and Chrome versions.
I decided to go with the Javascript Module Pattern, and I'm running into a problem with, for example, loading browser-specific preferences, saving data, and other browser-dependent stuff.
What I'd like to do is have the shared code reference virtual, overrideable methods that could be implemented in the derived, browser-specific submodules.
Here's a quick example of what I've got so far, that I've tried in the Firebug console, using the Tight Augmentation method from the article I referenced:
var core = (function(core)
{
// PRIVATE METHODS
var over = function(){ return "core"; };
var foo = function() {
console.log(over());
};
// PUBLIC METHODS
core.over = over;
core.foo = foo;
return core;
}(core = core || {}));
var ff_specific = (function(base)
{
var old_over = base.over;
base.over = function() { return "ff_specific"; };
return base;
}(core));
core.foo();
ff_specific.foo();
Unfortunately, both calls to foo() seem to print "core", so I think I've got a fundamental misunderstanding of something.
Essentially, I'm wanting to be able to call:
get_preference(key)
set_preference(key, value)
load_data(key)
save_data(key, value)
and have each browser do their own thing. Is this possible? Is there a better way to do it?
In javascript functions have "lexical scope". This means that functions create their environment - scope when they are defined, not when they are executed. That's why you can't substitute "over" function later:
var over = function(){ return "core"; };
var foo = function() {
console.log(over());
};
//this closure over "over" function cannot be changed later
Furthermore you are "saying" that "over" should be private method of "core" and "ff_specific" should somehow extend "core" and change it (in this case the private method which is not intended to be overridden by design)
you never override your call to foo in the ff_specific code, and it refers directly to the private function over() (which never gets overridden), not to the function core.over() (which does).
The way to solve it based on your use case is to change the call to over() to be a call to core.over().
That said, you're really confusing yourself by reusing the names of things so much, imo. Maybe that's just for the example code. I'm also not convinced that you need to pass in core to the base function (just to the children).
Thanks for your help. I'd forgotten I couldn't reassign closures after they were defined. I did figure out a solution.
Part of the problem was just blindly following the example code from the article, which meant that the anonymous function to build the module was being called immediately (the reusing of names Paul mentioned). Not being able to reassign closures, even ones that I specifically made public, meant I couldn't even later pass it an object that would have its own methods, then check for them.
Here's what I wound up doing, and appears to work very well:
var ff_prefs = (function(ff_prefs)
{
ff_prefs.foo = function() { return "ff_prefs browser specific"; };
return ff_prefs;
}({}));
var chrome_prefs = (function(chrome_prefs)
{
chrome_prefs.foo = function() { return "chrome_prefs browser specific"; };
return chrome_prefs;
}({}));
var test_module = function(extern)
{
var test_module = {};
var talk = function() {
if(extern.foo)
{
console.log(extern.foo());
}
else
{
console.log("No external function!");
}
};
test_module.talk = talk;
return test_module;
};
var test_module_ff = new test_module(ff_prefs);
var test_module_chrome = new test_module(chrome_prefs);
var test_module_none = new test_module({});
test_module_ff.talk();
test_module_chrome.talk();
test_module_none.talk();
Before, it was running itself, then when the extension started, it would call an init() function, which it can still do. It's just no longer an anonymous function.

Delegate Javascript Functions

As an siginificantly simplified scenario, say I have 2 Javascript objects defined as below:
var ClassA = Class.extend({
'say': function(message) {
console.log(message);
}
... // some more methods ...
});
var ClassB = Class.extend({
init: function(obj) {
this._target = obj;
}
});
I'd suppose that in Javascript there is some kind of mechanism could enable us to do the following trick:
var b = new ClassB( new ClassA() );
b.say("hello");
I'd like to find a way to detect if there is a method called upon ClassB, and the method is not defined in ClassB, then I can automatically forward the method call to be upon ClassA, which is a member variable in ClassB.
In a realworld scenario, ClassA is an object implemented as brwoser plugin and inserted into the webpage using <object> tag. It's method is implemented in C++ code so there is no way I can tell its methods from its prototype and insert it to ClassB's prototype beforehand.
I'd like to use the technical to create a native Javascript object, with a narraw-ed version of ClassA's interface. Is there a way I can do this?
I don't think there is a quick cross-browser solution to this.
If you only need Firefox, then use __noSuchMethod__
See here: is-there-such-a-thing-as-a-catch-all-key-for-a-javascript-object
and here: javascript-getter-for-all-properties
Otherwise, I would try something like this:
var b = new ClassB( new ClassA() );
// functionToCall is a string containing the function name
function callOnB(functionToCall) {
if(typeof b[functionToCall] === function) {
b[functionToCall]();
} else {
b._target[functionToCall](); // otherwise, try calling on A
}
}
This is using the Square Bracket Notation where
b.say('hello')
is the same as
b['say']('hello')
Of course, you should probably expand this to take arguments in:
function callOnB(functionToCall, listOfArguments) {...}
Thanks to jfrej's hint on noSunchMethod, I did some more research on it and it turns out what I need is quit fit with Harmony Proxies(here and here). And an example can be found at http://jsbin.com/ucupe4/edit#source
Another related post: http://dailyjs.com/2010/03/12/nosuchmethod/

Is this parasitic inheritence pattern any good?

Prototypal object creation in JavaScript is claimed to be powerful (I hear it is efficient and if used correctly very expressive). But for some reason I find that it trips me up much more often than it helps me.
The main problem I have with patterns for object creation involving prototype is that there is no way to bypass the need for this. The main reason is that objects that are anything beyond very primitive, for example objects that populate themselves through asynchronous API calls, this breaks down due to change of scope.
So, I use prototypal object creation for objects that I know everything about from the beginning.
But for objects that need to do for example API calls to keep themselves up to date I completely skip prototype and use straight up object literals.
When I feel the need for extending one of these objects, I have used parasitic inheritence:
var ROOT = ROOT || {};
ROOT.Parent = function () {
var self = {
func1 : function () {
alert("func1")
};
}
return self;
};
ROOT.Child = function () {
var self = ROOT.Parent(); // This is the parasitizing
self.func2 = function () {
alert("func2")
};
return self;
};
var myChild = ROOT.Child();
myChild.func1(); // alerts "func1"
myChild.func2(); // alerts "func2"
Using this pattern, I can reuse the code for func1 in the ROOT.Child object. However if I want to extend the code in func1 I have a problem. I.e if I want to call the code in the parents func1 and also my own func1 this pattern presents a challenge. I cannot do this:
ROOT.Child = function () {
var self = ROOT.Parent();
self.func1 = function () {
alert("func2")
};
};
Since this will completely replace the function. To solve this I have come up with the following solution (which you can also check out here: http://jsfiddle.net/pellepim/mAGUg/9/).
var ROOT = {};
/**
* This is the base function for Parasitic Inheritence
*/
ROOT.Inheritable = function () {
var self = {
/**
* takes the name of a function that should exist on "self", and
* rewires it so that it executes both the original function, and the method
* supplied as second parameter.
*/
extend : function (functionName, func) {
if (self.hasOwnProperty(functionName)) {
var superFunction = self[functionName];
self[functionName] = function () {
superFunction();
func();
};
}
},
/**
* Takes the name of a function and reassigns it to the function supplied
* as second parameter.
*/
replace : function (methodName, func) {
self[methodName] = func;
}
};
return self;
};
/**
* "Inherits" from ROOT.Inheritable
*/
ROOT.Action = function () {
var self = ROOT.Inheritable();
/**
* I intend to extend this method in an inheriting object
*/
self.methodToExtend = function () {
alert("I should be seen first, since I get extended");
};
/**
* I intend to replace this method in an inheriting object
*/
self.methodToReplace = function () {
alert("I should never be seen, since I get replaced.");
};
return self;
};
/**
* "Inherits" from ROOT.Action.
*/
ROOT.Task = function () {
var self = ROOT.Action();
self.extend('methodToExtend', function () {
alert("I successfully ran the extended code too.");
});
/**
* I know it is completely unecessary to have a replace method,
* I could just as easily just type self.methodToReplace = function () ...
* but I like that you see that you are actually replacing something.
*/
self.replace('methodToReplace', function () {
alert("I successfully replaced the \"super\" method.");
});
return self;
};
var task = ROOT.Task();
task.methodToExtend(); // I expect both the "base" and "child" method to run.
task.methodToReplace(); // I expect only the "child" method to run.
Ok, so I should ask a question. Am I completely off target here or am I on to something? What are the apparent drawbacks?
No, you're not off target. But you did not invent that wheel also. That type of ECMAscript inheritance became very famous with Doug Crockfords book Javascript: The good parts.
It is a nice pattern and uses closures nicely to keep things private and protected. However, it's still up to you which patterns you prefer (plain prototypal inheritance, pseudo-classical).
With ES5 and new possiblitys like Object.create() and Object.defineProperties(), Object.freeze() to name a few, we also have good ways to have protection and privacy with a more prototypal approach. Personally, I still prefer and like the pseudo classical way, using closures to do stuff.
The caveat still might be function-calls overhead which you generally can avoid using a plain prototypal inheritance. We need to make a whole lot more calls to get things properly done (if things grows). Still, closures are considered to be a little memory greedy and probably be a reason for leaks if we use them sloppy or forget to clean up references here and there. I don't have any reference for this now, but I strongly believe that the latest js engines are not much slower using closures like a lot.

Categories