Skip to content

Instantly share code, notes, and snippets.

@fogus
Created June 1, 2011 17:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save fogus/1002886 to your computer and use it in GitHub Desktop.
Save fogus/1002886 to your computer and use it in GitHub Desktop.
mvf.js
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?
@md2perpe
Copy link

md2perpe commented Jun 1, 2011

You cannot.

At the end of your script you will have like

inst = {
    m: function() { return 42 } };
    f: function() { return 42 } };
}

Thus, no difference between m and f.

@ohpauleez
Copy link

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.

@md2perpe
Copy link

md2perpe commented Jun 1, 2011

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.

@ohpauleez
Copy link

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.

@md2perpe
Copy link

md2perpe commented Jun 1, 2011

If one uses a prototype to define methods, like this, one should be able to differ between methods and "fields".

@fogus
Copy link
Author

fogus commented Jun 1, 2011

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.

Copy link

ghost commented Jun 1, 2011

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.

@founddrama
Copy link

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; };

@founddrama
Copy link

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment