-
-
Save fogus/1002886 to your computer and use it in GitHub Desktop.
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? |
That's not true, you could look at the ancestor object and see if it hasOwn for both f and m (and that they are defined as functions). This would only work assuming nothing adds a function f to M. You could additionally abuse the name field of the m, to "color" it as a method, or tack on extra properties. I feel like I've read something on this subject matter in JavaScript Patterns (Stefanov) before.
I suppose you're referring to the method hasOwnProperty. That's not relevant in this case; the given example has nothing to do with ancestry.
Ah, you're right, I wasn't thinking clearly. You're right, because of hoisting, you'll end up with something like you described.
I still feel like there's a way to do this.
If one uses a prototype to define methods, like this, one should be able to differ between methods and "fields".
Yes, if I control the construction mechanism of all instances that I care about then this is a trivial problem. However, the real question is if it's possible to do so for any object.
It can't be done. Methods have no idea that they are special in any way from regular functions. Here is a modified version of what you have written to demonstrate the point.
var M = function() { this.m = function() { return this.r }; this.r = 42 };
var inst = new M();
var f = inst.m;
inst.m(); // => 42
f(); // => undefined
var r = 45;
f(); // => 45
The way I understand things is that "this" is always bound dynamically each time a function is called unless you use bind to fix it to a specific object. So there is no way to get the context of the function and see if it's bound to anything and distinguish it from a regular function.
In your example, the method assignments are functionally equivalent -- this
in the constructor is going to be ==
your inst
; the interpreter doesn't keep track of ("doesn't care") whether the value at a given field is assigned as part of the constructor's operation, or if it's assigned later. So the short answer is: "No, you can't write an is_method
."
What you're looking for is probably something more like this:
M.prototype.m = function() { return this.v; };
In your example, the method assignments are functionally equivalent -- this
in the constructor is going to be ==
your inst
; the interpreter doesn't keep track of ("doesn't care") whether the value at a given field is assigned as part of the constructor's operation, or if it's assigned later. So the short answer is: "No, you can't write an is_method
."
What you're looking for is probably something more like this:
var M = function() { this.v = 42; };
M.prototype.m = function() { return this.v; };
var inst = new M();
inst.f = function() { return this.v; };
inst.hasOwnProperty('f');
// true
inst.hasOwnProperty('m');
// false
You cannot.
At the end of your script you will have like
Thus, no difference between m and f.