Is your mixin really compatible with ECMAScript 5? _ Basics

Source: Internet
Author: User
Tags hasownproperty

I recently worked on a project with a client that needs to be fully utilized by ECMAScript 5, where I met a very interesting question. The problem stems from a very common pattern: mixin, which mixin the attributes or methods of an object to another in JavaScript.

Most mixin features look like this:

Copy Code code as follows:

function Mixin (receiver, supplier) {
For (Var property in supplier) {
if (Supplier.hasownproperty (property)) {
Receiver[property] = Supplier[property];
}
}
}

In this mixin () function, a for loop traverses the properties of the Supplier object and assigns it to the receiver object. Almost all JavaScript libraries have some form of similar functionality that allows you to write code like this:

Copy Code code as follows:

Mixin (object, {
Name: "Nicholas",

Sayname:function () {
Console.log (this.name);
}
});

Object.sayname (); Outputs "Nicholas"

In this example, object objects receive the property name and Method Sayname (). This works well in ECMAScript 3, but not so optimistic on ECMAScript 5.

This is the problem I encountered:

Copy Code code as follows:

(function () {

To is filled in later
var name;

Mixin (object, {
Get Name () {
return name;
}
});

Let ' s just say this is later
Name = "Nicholas";

}());

Console.log (Object.name); Undefined

This example looks a bit contrived, but it accurately describes the problem. The properties for mixin use the new feature of ECMAScript 5: A getter property accessor. The getter references an uninitialized local variable name, so this property does not define undefined.

Later, name is assigned a value so that the accessor getter can return a valid value. Unfortunately, Object.name (the mixin attribute) always returns to undefined.

What the hell is going on here?

We carefully analyze the mixin () function. In fact, in a loop statement, the attribute is not assigned to another object from one object. It actually creates an attribute with the same name and assigns the return value of the accessor method getter for the supplier object to it. The target object does not get the Getter method, but it gets the return value of the Getter method. @justjavac)

In this example, the process of mixin () is actually this:

Copy Code code as follows:

Receiver.name = Supplier.name;

The property Receiver.name is created and is assigned a value of Supplier.name. Of course, Supplier.name has a getter method to return the value of the local variable name. At this point, the value of name is undefined, so receiver.name stores the value. There is no Getter method created for Receiver.name, so its value never changes.

To solve this problem, you need to use the attribute descriptor (descriptor) to mixin attributes from one object to another. A pure ECMAScript 5 version of Mixin () should be written like this:

Copy Code code as follows:

function Mixin (receiver, supplier) {

Object.keys (supplier). ForEach (function (value, property) {
Object.defineproperty (receiver, property, Object.getownpropertydescriptor (Supplier, property));
});
}

In this new version of this function, Object.keys () is used to get an array containing all the enumeration properties of the Supplier object. The foreach () method is then used to traverse these properties. Call the Object.getownpropertydescriptor () method to get each property descriptor (descriptor) of the Supplier object.

Because the descriptor (descriptor) contains all the property information, including the getter and setter methods, the descriptor (descriptor) can be passed directly to Object.defineproperty (), which is used to receiver object to create the same properties on the Using this new version of Mixin (), you can solve the problems you've encountered before and get the results you expect. The getter method is correctly passed from supplier to the receiver.

Of course, if you still need to support old browsers, then you'll need a function that falls back on the ECMAScript 3:

Copy Code code as follows:

function Mixin (receiver, supplier) {
    if (Object.keys) {
        Object.keys (supplier). ForEach (function (value, property) {
            Object.defineproperty (receiver, property, Object.getownpropertydescriptor (supplier, property));
       });
   } else {
        for (Var property in supplier) {
&nbs p;           if (supplier.hasownproperty) {
                 Receiver[property] = Supplier[property];
           }
       }
   }
}

If you need to use a mixin () function, be sure to double-check that it works in ECMAScript 5, especially the getter and setter methods. Otherwise, you will find yourself in a mistake like mine.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.