torsdag, september 13, 2007

JavaScript ignorance

Put it down to my general ignorance - I've never realized that JavaScript has send/perform, and has had it for a long, long time. Of course, it only works for methods that exists on the object. Or? Is there any way of capturing non-existent method-calls/property look-ups like method_missing does?

Anyway, send:
function SendTester() {}
SendTester.prototype.foo = function() {
print("Hello");
};

new SendTester().foo();
var name = 'foo';
new SendTester()[name]();
Please, tell me something more cool I've been able to do in JavaScript in browsers for 5-10 years but didn't know about!

9 kommentarer:

Scott sa...

You can use the hasOwnProperty method of the Object.

http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Object:hasOwnProperty

or the in operator.
http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Operators:Special_Operators:in_Operator

Both of those methods just check the instance of the object, and don't look up the objects prototype chain. I believe you can query the prototype property directly to check for a specific member.

I'd recommend any of the videos that Douglas Crockford did for Yahoo. He does a really good job of explaining how Javascript came about and how to really use the language. I learn something new every time I re-watch the series.

grundprinzip sa...

If you look at send methods in JavaScript what about the apply method that is in combination to the above mentioned example pretty cool as well.

The apply method lets you execute any function in a given context. The following example will show how this works:


function K1() {
K1.prototype.text = "";

K1.prototype.test = function(){
alert(this.text)
};

}

function K2(){
K2.prototype.text = "";
}

k = new K1();
k.text = "Hello";

l = new K2();
l.text = "Welcome";


k.test()
k.test.apply(l)

On l the method test is not defined, but we use the context of l to get the variable text. The result will be a alert box once with the value Hello and once with the value Welcome Of course this is more or less a misuse of the apply method, but shows the power of prototyped languages.

See you at the RailsConf in Berlin.

Martin

Anonym sa...

Tools like "ruby.js" provide some close-but-not-quite-there Rubification of JS.

It's "send()" function with a little tweaking would allow your classes to implement a method_missing. Here's a possible tweak...


// Change the send method in ruby.js to defer to a method_missing function
Object.prototype.send = function(method) {
var rest = arguments.toArray().last(-1)
if (!this.respondTo(method)) {
this.method_missing(method)
} else {
return(this[method].apply(this, rest))
}
}

// Provide a default method_missing function which throws the exception
Object.prototype.method_missing = function(method) {
throw("Undefined method '" + method + "'")
}


BUT - the problem is that it relies on the caller to always be using the clunky myObject.send("methodName") syntax.

The power of method_missing (actually Ruby's metaprogramming model) is that it allows the caller to use normal syntax and the callee deals with translation.

For JavaScript, you just have to hope the
http://wiki.ecmascript.org/doku.php?id=proposals:catchalls proposal makes it into EcmaScript4, where the "invoke()" meta function will solve the woes.

Anonym sa...

you can use __noSuchMethod__ or somesuch in mozilla for the equivalent method_missing.

Robin Hood sa...

Isn't it the way like jQuery works? I don't know for sure, but it seem the same way

Julien Couvreur sa...

It is useful to read the ECMAScript spec to get a deeper understanding of javascript. It's kind of dry though ;-)

Alek Traunic sa...

(function(){
    var SendTester = function(){
        return{
            foo: function(){
                alert("hello");
            },
            "bar with space": function(){
                alert("world");
            }
        }
    }
    var name1 = "foo";
    var name2 = "bar with space";
    SendTester()[name1]();
    SendTester()[name2]();
})();

Christophe Grand sa...
Den här kommentaren har tagits bort av skribenten.
Christophe Grand sa...

__noSuchMethod__ exists in Spidermonkey and in Rhino.