Pergunta

Can anyone explain the process JavaScript goes through when a method is called to select which function is run? Most resources online I could find explain how to achieve specific behaviours using JavaScript object, but not the general principle behind how method dispatch works in JavaScript.

Foi útil?

Solução

"Method dispatch" is actually just property lookup, because "methods" in JavaScript are just functions used via object properties. (More about that on my blog: Mythical methods)

When you write:

obj.prop

the JavaScript engine looks at the obj object to see if it has a property with the name "prop". If it does, the value of that property is used. If it doesn't, the engine looks the the prototype object for obj to see if it has a property with that name. If so, it uses the value of it. If not, it looks at that object's prototype. Rinse, repeat, until it runs out of prototype objects.

There is no "method signature" matching of any kind as in some languages that allow method overloading. JavaScript doesn't have method overloading. There can only be one propety attached to an object with a given name.

Let's look at an example:

function Thing() {
}
Thing.prototype.test = function() {
    return "Thing#test";
};

var t = new Thing();
t.own = function() {
    return "My own";
};

Now let's play with t:

console.log(t.own());  // Logs "My own"

For the expression t.own, the engine looks at t to see if it has a property called "own". It does, and so the value of that property (a function) is used. The () after it calls that function, which returns "My own", and we're done.

console.log(t.test()); // Logs "Thing#test"

For the expression t.test, the engine looks at t to see if it has a property called "test". It doesn't, so the engine looks at t's prototype. t's prototype is Thing.prototype, which was assigned to it during the expression new Thing. Thing.prototype has a "test" property, so the value of that ( a function) is used. Then the () after it calls that function, which returns the string "Thing#test".

console.log(t.toString()); // Logs "[object Object]"

The engine looks at t, doesn't find a "toString" property, so it looks at t's prototype, and doesn't find a "toString" property, so it looks at t's prototype's prototype (which is Object.prototype). That does have a "toString" property, whose value is a function. Then () calls the function, which returns "[object Object]".

And finally, for completeness:

console.log(t.foo());      // Throws an error

The engine doesn't find "foo" on t, t's prototype, or t's prototype's prototype. Now it's out of prototypes, so the expression t.foo results in undefined. Then we try to call it via (), which we can't do because undefined is not a function.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top