14

I saw this in an auto-generated javascript file:

function map(x){
    x={x:x};
    delete x.x;
    return x
}

My conclusion is that is used to create an object, but why create it in that way? Is it a pattern?

UPDATE

More info, the tool that created this code is dart2js from Google, the code is used in this context:

(function (reflectionData) {
  function map(x){x={x:x};delete x.x;return x}
  if (!init.libraries) init.libraries = [];
  if (!init.mangledNames) init.mangledNames = map();
  if (!init.mangledGlobalNames) init.mangledGlobalNames = map();
  if (!init.statics) init.statics = map();
  if (!init.interfaces) init.interfaces = map();
iConnor
  • 19,997
  • 14
  • 62
  • 97
user2070369
  • 3,970
  • 6
  • 22
  • 32
  • try it yourself. It is not that complicated – karthikr Oct 03 '13 at 18:48
  • 4
    I did, it creates an empty object. – user2070369 Oct 03 '13 at 18:48
  • And if so, what not just `return {};`??? Or `var x={}; return x;` if there's some syntactic subtlety with the former? – Lawrence Dol Oct 03 '13 at 18:49
  • It is basically creating a mapping `{key: key}` and deleting the `key `and returning an empty dictionary object. as good as `function map(x): return {}` – karthikr Oct 03 '13 at 18:50
  • 1
    Of course, it might just be a case of lemming programming. – Lawrence Dol Oct 03 '13 at 18:50
  • 8
    Where did this come from? It looks more like a code puzzle than something you'd actually see in a real library - like it's in a javascript quiz or something. – Joe Enos Oct 03 '13 at 18:50
  • 3
    Looks really stupid to me. – ChaosPandion Oct 03 '13 at 18:51
  • 2
    If it's auto-generated, it's possible that the generator just isn't sophisticated enough to use a different pattern for a trivial case. – JJJ Oct 03 '13 at 18:54
  • 2
    Auto generated code tends to make little sense from time to time in many different languages. I've seen loads of crap like like this. Here's some auto-generated brilliance from a Java codebase. `if(true == true)`, `{String result = ""; return null;}`, `catch(Exception ex){ throw new Exception(null);}`. Not to mention several-hundred-lines-long methods that literally do nothing apart from crashing occasionally. – toniedzwiedz Oct 03 '13 at 18:54
  • How to get rep in stack overflow: Post a simple answer that looks correct. It doesn't matter if it actually answers the question, the upvotes will still come – Sam I am says Reinstate Monica Oct 03 '13 at 18:55
  • Auto-generated or not, that looks asinine, at least to me. I can't see a non-"trivial" case where it might do something useful. – Lawrence Dol Oct 03 '13 at 18:55
  • 1
    What generator was used for this? I suspect that it's probably designed to support older versions of browsers, where the literal {} might have caused problems – SheetJS Oct 03 '13 at 19:00
  • 2
    This question has been a rollercoaster of votes. Note that the question title states what is the code supposed to do (not why). Personally I'd love to know what generated the code, that is the only way to answer the question properly. – Daniel Imms Oct 03 '13 at 19:01
  • 1
    @Software, I've been wondering for a while why the function is called `map()` but only takes a single argument. Mapping requires at least two arguments, and `this` is not used either, so I think the function is supposed to take more than one argument and would generate more understandable code under these conditions. – Frédéric Hamidi Oct 03 '13 at 19:01
  • 5
    Given that this question can't be answered (due to not enough context - and see the negative downvotes below as a result), I believe this should be closed. – JasCav Oct 03 '13 at 19:01
  • @Nirk But why should the function be called `map` which accepts a useless argument? – ComFreek Oct 03 '13 at 19:02
  • 13
    In the dart source, there's a comment which says that this technique is used for v8 performance reasons: https://github.com/dart-lang/bleeding_edge/blob/4dde22bc006605fc168cefcc0807c43354463b6e/dart/sdk/lib/_internal/compiler/implementation/js_emitter/reflection_data_parser.dart#L17-L19 – SheetJS Oct 03 '13 at 20:56
  • 2
    @ComFreek in context, "map" is actually an associative map – SheetJS Oct 03 '13 at 20:58
  • 2
    @Nirk, so you mean `x` is always supposed to be `undefined` in calls to `map()`... Your comments are the answer and should be posted as such. Voted to reopen. – Frédéric Hamidi Oct 05 '13 at 12:11
  • Per @Nirk's comment: here's a [video on hidden classes](http://www.youtube.com/watch?v=UJPdhx5zTaw&feature=player_detailpage#t=630) from Google I/O 2012. – apsillers Oct 08 '13 at 19:15

3 Answers3

11

In the dart source, there's a comment which says that this technique is used for v8 performance reasons:

// [map] returns an object literal that V8 shouldn't try to optimize with a
// hidden class. This prevents a potential performance problem where V8 tries
// to build a hidden class for an object used as a hashMap.

https://github.com/dart-lang/bleeding_edge/blob/4dde22bc006605fc168cefcc0807c43354463b6e/dart/sdk/lib/_internal/compiler/implementation/js_emitter/reflection_data_parser.dart#L17-L19

The word map here refers to an associative array

SheetJS
  • 22,470
  • 12
  • 65
  • 75
10

I read a article about this a while ago actually and apparently if you delete something from a object, V8 puts the object into Dictionary Mode or Slow Mode and then properties are stored in a "hash table".

V8 can handle minor divergences like this just fine, but if your code assigns all sorts of random properties to objects from the same constructor in no particular order, or if you delete properties, V8 will drop the object into dictionary mode, where properties are stored in a hash table. This prevents an absurd number of maps from being allocated.

This is the article http://www.jayconrod.com/posts/52/a-tour-of-v8-object-representation it explains it in there along with other things.

I may be wrong but I think this is used for Large (in size and life) objects to increase performance and decrease the chance of a memory leak.

This is on the same sort of topic

Does using delete keyword effect v8 optimizations of an object?

iConnor
  • 19,997
  • 14
  • 62
  • 97
9

The purpose of the map function is to create an associative-map object whose set of properties can be quickly altered.

The natural question arrises: aren't all JavaScript objects already maps by default? Yes, they are! The EMCAScript specification allows objects to add or drop properties at any time, allowing them to function as associative maps.

But, alas, the low-level language that is responsible for implementing the JavaScript execution environment (likely C++) is not so easygoing. In particular, V8 uses a concept called hidden classes, whereby the addition of a property to a JavaScript object will cause the creation of a new C++ class. V8 does this as an optimization because it assumes your code will repeatedly use a small set of object types.

For example, you have a Bullet type with x, y, dx, and dy properties. In practical terms, these types are fixed; it's not likely that you would suddenly add on a new property to a Bullet object on the fly. The hidden-class optimization means that using a fixed set of object types runs very quickly, but it also means that, sometimes, the real cost of adding a new property to a JS object can be quite high, because it prompts the creation of a new C++ class that has the new property.

By introducing a delete operation on the object x, you signal to the V8 engine that this object x will not benefit from the hidden-class optimization. The idea behind hidden classes is that your objects will not usually change their set of properties (except adding new properties at construction time). By doing a delete you unequivocally signal that this object will change its property set in ways that make hidden classes totally unhelpful. For this object, the cost of creating hidden classes far outweighs the benefits.

Thus, the object returned by map will be excluded from V8 hidden-class optimizations, allowing it to add and remove arbitrary properties much more quickly.

apsillers
  • 112,806
  • 17
  • 235
  • 239