Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does javascript concatenate function names in multiple assignment to properties?

This is an edge case and probably bad practice, but it made me curious about some js internals. Can anyone explain why chrome dev tools tells me that I have created a function named a.a.b.b here?

enter image description here

Note that this does not happen unless you are assigning to a property. Otherwise both a and b appear to refer to a function object named 'b':

enter image description here

By the way, I originally encountered this here when trying to answer my own question about dat.gui.js .

like image 963
foobarbecue Avatar asked Oct 20 '22 10:10

foobarbecue


1 Answers

This has nothing to do with the language spec.
It's a DevTools enhancement for debugging convenience, which is ported recently in Chrome.

Remember what we used to do?

function F() {}
// notice it's a NAMED function expression
F.prototype.asdf = function _asdf() { debugger; }; 

var f = new F();
f.asdf();

Then in breakpoint debugging, we can find the method by its name _asdf from function call stack. Otherwise it's the pain in the ass to do that from a list of (anonymous function).

enter image description here

In latest Chrome, when you assign an anonymous function as an object property, an alias will be attached to it.

var a = {}, b = {};
a.a = b.b = function() { debugger; };
a.b = b.a = function _abba() { debugger; };

Remember, it's just a DevTools enhancement, the method remains anonymous:

a.a.name; // ""
a.b.name; // "_abba"

But it's very helpful in breakpoint debugging:

a.a();
a.b();

enter image description here


EDIT:

I'm not very sure why the alias is generated as a.a.b.b, it looks very easy but kind of... stupid. However, in practice we seldom do a.a = b.b = func... thing (lucky). Instead, we define a method in one place, and do inheritence when necessary, rather than copy reference directly.

So in a good programming practice, the alias should and would exactly reflect where you define the method. For example, alias Dog.bark in breakpoint clearly maps to Dog.prototype.bark in source code, even if it's called on a Puppy instance, and we don't have to do old school named function expression.

function Dog() {}
Dog.prototype.bark = function() { alert("Woof!") }; // anonymous function expression here
function Puppy() {}
Puppy.prototype = new Dog();

(new Puppy()).bark(); // break point alias -> Dog.bark

One more thing, when I discovered this feature, I can't stop thinking of it - does it imply that Chrome will implement ES6 class very soon? How exciting!

like image 102
Leo Avatar answered Oct 22 '22 01:10

Leo