How does JavaScript VM implements Object property access? Is it Hashtable?

前端 未结 4 1143
故里飘歌
故里飘歌 2020-11-29 05:10

Objects in JavaScript can be used as Hashtable (the key must be String) Is it perform well as Hashtable the data structure?

I mean , does it implemented as Hashtable

4条回答
  •  死守一世寂寞
    2020-11-29 06:02

    Most modern JS engines use pretty similar technique to speed up the object property access. The technique is based on so called hidden classes, or shapes. It's important to understand how this optimization works if you want to write efficient JS code.

    JS object looks like a dictionary, so why not use one to store the properties? Hash table has O(1) access complexity, it looks like a good solution. Actually, first JS engines have implemented objects this way. But in static typed languages, like C++ or Java a class instance property access is lightning fast. In such languages a class instance is just a segment of memory, end every property has its own constant offset, so to get the property value we just need to take the instance pointer and add the offset to it. In other words, in compile time an expression like this point.x is just replaced by its address in memory.

    May be we can implement some similar technique in JS? But how? Let's look at a simple JS function:

    function getX(point) {
      return point.x;
    }
    

    How to get the point.x value? The first problem here is that we don't have a class (or shape) which describes the point. But we can calculate one, that is what modern JS engines do. Most of JS objects at runtime have a shape which is bound to the object. The shape describes properties of the object and where the properties values are stored. It's very similar to how a class definition describes the class in C++ or Java. It's a pretty big question, how the Shape of an object is calculated, I won't describe it here. I recommend this article which contains a great explanation of the shapes in general, and this post which explains how the things are implemented in V8. The most important thing you should know about the shapes is that all objects with the same properties which are added in the same order will have the same shape. There are few exceptions, for example if an object has a lot of properties which are frequently changed, or if you delete some of the object properties using delete operator, the object will be switched into dictionary mode and won't have a shape.

    Now, let's imagine that the point object has an array of properties values, and we have a shape attached to it, which describes where the x value in this property array is stored. But there is another problem - we can pass any object to the function, it's not even necessary that the object has the x property. This problem is solved by the technique called Inline caching. It's pretty simple, when getX() is executed the first time, it remembers the shape of the point and the result of the x lookup. When the function is called second time, it compares the shape of the point with the previous one. If the shape matches no lookup is required, we can take the previous lookup result.

    The primary takeaway is that all objects which describe the same thing should have the same shape, i.e. they should have the same set of properties which are added in the same order. It also explains why it's better to always initialize object properties, even if they are undefined by default, here is a great explanation of the problem.

    Relative resources:

    • JavaScript engine fundamentals: Shapes and Inline Caches and a YouTube video
    • A tour of V8: object representation
    • Fast properties in V8
    • JavaScript Engines Hidden Classes (and Why You Should Keep Them in Mind)
    • Should I put default values of attributes on the prototype to save space?

提交回复
热议问题