A JavaScript Puzzler
[sourcecode lang=”javascript” gist=”1002886″]var M = function() { this.m = function() { return 42 } };
var inst = new M();
inst.f = function() { return 42 };
// How to tell that f is a function in a field and // m is a method in an arbitrary object? // // example:
is_method(inst.f); //=> false
is_method(inst.m); //=> true
// Is it possible to write is_method? [/sourcecode]
7 Comments, Comment or Ping
John Weir
I don’t know of a way.
Also, assigning functions to the object via “this” in the constructor will generate new, unique, functions for each instance.
Consider
Is using prototype an option?
var M = function(){} M.prototype.m = function() { return 42 }
var inst = new M() inst.f = function() { return 42 }
function is_method(o,name){ var p = o.constructor.prototype return p[name] && p[name] === o[name] }
is_method(inst,”f”) is_method(inst,”m”) // true
Jun 1st, 2011
adrusi
I don’t thinks so, but if you redesigned the syntax to
is_method(inst, "f")
it should be, by comparing the constructor’s prototype with the actual object. Something along the lines of:This isn’t tested, but it should work as it is or with a few modifications.
Jun 1st, 2011
mpenet
I don’t think it’s possible, from my understanding they are essentially the same, the only difference is at what time you assign these “methods” to instances.
Both aren’t present M.prototype
I am not sure what you are trying to achieve but this might help you figure it out:
https://gist.github.com/1004051
Jun 2nd, 2011
Yoav
If we assume that you know what is the constructor function, then you can :
1) take the code of the constructor by doing ctorCode = M.toString(); 2) the is_method function creates some RegExp based on the name of the method you sent and searches for that string in the constructor (by searching for ‘this’ followed by zero or more spaces then looking for dot (note that . means anything in RegExp) then again zero or more spaces then the name of the method and then again zero or more spaces followed by = (and on and on look for ‘function’ and ‘(‘ )
If there’s a match, then this is a method.
Also, if you define a method also functions that came from the prototype chain, then you need to use the method hasOwnProperty. Basically, if the object has that method and hasOwnProperty returns false, then it’s from the prototype chain.
Jun 2nd, 2011
Daniel Spiewak
The distinction between m and f is artificial. They are, for all intents and purposes, the exact same language element. In fact, they are added using exactly the same method right after each other. Just extract the “this.m = …” code outside the function (obviously changing “this” to “inst”) and you’re done.
So there’s nothing magical about “m” vs “f”, and thus no way to tell them apart. Not sure why you would want to, either, they really are exactly the same.
Jun 2nd, 2011
amac
I think I’ve got a nice solution here:
The functions in M’s fields are associated with M’s object as their parent when inst is built; whereas anonymous functions which are not associated in the object prototype are not constructed and thus don’t have a parent constructor.
After re-writing this explanation 4 times, this was the clearest I could articulate it — sorry.
Jun 16th, 2011
amac
there should be two underscores to each side of the parent magic value, I’m unfamiliar with the markup here.
Jun 16th, 2011
Reply to “A JavaScript Puzzler”