I was recently working on a project with a client that needed to take full advantage of ECMAScript 5, and I encountered a very interesting problem. The problem stems from a very common pattern: mixins, which are mixing properties or methods of one object into another in JavaScript.
The functionality of most mixins looks like this:
Copy code
In this example, the object object receives the property name and the method sayName(). This works fine in ECMAScript 3, but not so much in ECMAScript 5.
This is the problem I'm having:
Copy code
}
});
// let's just say this is later
name = "Nicholas";
}());
This example looks a bit contrived, but it accurately describes the problem. The properties that are mixed in use a new feature of ECMAScript 5: a getter property accessor. The getter refers to an uninitialized local variable name, so the property is undefined.
Later, name is assigned a value so that the accessor getter can return a valid value. Unfortunately, object.name (the mixined property) always returns undefined.
Let’s analyze the mixin() function carefully. In fact, in the loop statement, the properties are not reassigned from one object to another object. It actually creates a property with the same name and assigns it the return value of the supplier object's accessor method getter. (Annotation: The target object does not get the getter method, but the return value of the getter method. @justjavac)
In this example, the mixin() process is actually like this:
Copy code
Copy code
In this new version of the function, Object.keys() is used to obtain an array containing all enumeration properties of the supplier object. The foreach() method is then used to iterate over these properties. Call the Object.getOwnPropertyDescriptor() method to obtain each property descriptor (descriptor) of the supplier object.
Since the descriptor contains all property information, including getter and setter methods, the descriptor can be passed directly to Object.defineProperty() to create the same property on the receiver object. Using this new version of mixin(), you can solve the problems encountered earlier and get the results you expect. The getter method is correctly passed from supplier to receiver.
Of course, if you still need to support older browsers, then you'll need a function that falls back to ECMAScript 3:
If you need to use a mixin() function, be sure to double check that it works properly in ECMAScript 5, especially the getter and setter methods. Otherwise, you'll find yourself falling into mistakes like I did.