Jquery.extend () method and JQuery.fn.extend () method source code Analysis

Source: Internet
Author: User
Tags throw exception

The two methods use the same code, one for the jquery object or for the common object, and one for the jquery object instance, and for the basic usage, give a few examples:

The HTML code is as follows:

<!DOCTYPE HTML><HTML>   <Head>      <title></title>        <Scriptsrc= ' Jquery-1.7.1.js '></Script>   </Head>   <Body>      <imgsrc= ' '/>   </Body></HTML>

The following is the use of JS inside:

Merge two Common objects

      // Combine attributes      for two ordinary objects var obj1={name: ' Tom ', age:22};       var obj2={name: ' Jack ', height:180};      Console.log ($.extend (OBJ1,OBJ2));   //object {name: "Jack", Age:22, height:180}

Add a property or method to a jquery object

$.extend ({hehe:function() {alert (' hehe ');}});

$.hehe (); // alert (' hehe ')

This usage is very important, is that jquery internal add instance properties and methods as well as the prototype properties and methods of implementation is also the method of writing jquery plug-ins, the following is the use of the Extend method to extend their own methods and properties jQuery1.7.1

jquery.extend ({noconflict:function(deep) {if(window.$ = = =jQuery) {window.$= _$; }        if(Deep && window.jquery = = =jQuery) {Window.jquery=_jquery; }        returnJQuery; },    //Is the DOM ready to be used? Set to True once it occurs.IsReady:false,    //A counter to track how many items to wait for before    //The Ready event fires. See #6781Readywait:1,
.....

In this example, only one object parameter is passed, and this is used by default as the object to be modified by the merge.

Add a property or method to a jquery object instance

// Expand Merge      for jquery instance Console.log ($ (' img '). Extend ({' title ': ' img '}); // [img, img#img.img, prevobject:jquery.fn.jquery.init[1], context:document, selector: "img", Title: "IMG", Constructor:function ...]

Merge not modify objects to merge only

      var obj1={name: ' Tom ', age:22};       var obj2={name: ' Jack ', height:180};      Console.log ($.extend (OBJ1,OBJ2));    // Object {name: "Jack", Age:22, height:180}      Console.log (obj1);                  // Object {name: "Jack", Age:22, height:180}

By default, the object to be merged is the same as the returned result, which can be used if you want only one of the merged objects to destroy any of the original objects.

  var obj1={name: ' Tom ', age:22};   var obj2={name: ' Jack ', height:180};   var empty={};  Console.log ($.extend (EMPTY,OBJ1,OBJ2));    // Object {name: "Jack", Age:22, height:180}  Console.log (obj1);                  // Object {name: "Tom", age:22}

Use recursive merge or call deep copy

var obj1={name: ' Tom ', Love:{drink: ' Milk ', eat: ' Bread 'var obj2={name: ' Jack ', Love:{drink: ' Water ', sport: ' Football '};   Console.log (($.extend (false, Obj1,obj2)).   // Object {drink: "Water", Sport: "Football"} Console.log (($.extend (true, Obj1,obj2)). Love);    // Object {drink: "Water", Eat: "Bread", Sport: "Football"}

Detailed use of the method can be seen in the reference manual http://www.w3cschool.cc/manual/jquery/

Below to analyze the 1.7.1 source code is how to achieve:

function () {    var  options, name, SRC, copy, Copyisarray, clone,        = arguments[0] | |  {},         = 1,        = arguments.length,        false;       ...}

The first is to define a set of variables, because the number of arguments is not deterministic, so we call directly the arguments object to access the passed parameters

Variable options: Point to a source object.
? ? Variable Name: Represents a property name for a source object.
? ? Variable src: Represents the original value of a property of the target object.
? ? Variable copy: Represents the value of a property of a source object.
? ? Variable Copyisarray: Indicates whether the variable copy is an array.
? ? Variable clone: Represents the corrected value of the original value when deep replication occurs.
? ? Variable target: Points to the target object.
? ? Variable i: Indicates the starting subscript of the source object.
? ? Variable length: Indicates the number of arguments used to correct the variable target.
? ? Variable Depth: Indicates whether deep replication is performed and defaults to False.

To better understand the implementation of the code here is an example of how to observe the source code execution

      var obj1={name: ' Tom ', Love:{drink: ' Milk ', eat: ' Bread '};       var obj2={name: ' Jack ', Love:{drink: ' Water ', sport: ' Football '};      $.extend (true, Obj1,obj2)

SOURCE Analysis

// Handle a deep copy situation    if typeof target = = = "Boolean" ) {        = target;         = Arguments[1] | |  {};         // Skip the Boolean and the target        i = 2;    }

The judge is not deep copy, if the first parameter is a Boolean value, then the value of the first parameter to the depth, and then the second parameter as the target object, if the second parameter does not exist to assign to an empty object, the source object's subscript is changed to 2, in this example It's here. Because the first parameter is ture and then the deep becomes true, the target is fixed to the second parameter, which is the obj1, the source object starts with an index of 2, which is the third starting as the source object, which is the obj2 in this case.

// Handle Case If Target is a string or something (possible in deep copy)    if typeof Target!== "Object" &&! jquery.isfunction (target)) {        = {};    }

The target is further processed here. Adding custom attributes to non-object and function data types is not valid, such as the method and property that the string self-can call comes with

// extend JQuery itself if only one argument is passed    if (length = = = I        ) {This        ; --i;    }

If the Length property equals the value of I that means there is no target object exists, and normally length should be greater than the value of I, then this time as the target object to the I value minus one implementation length value is greater than I value (greater than I 1)

This is how jquery gives itself the ability to extend properties, as long as the target object is not passed in.

Two possible scenarios: $.extend (obj) or $.extend (false/true,obj);

     for(; i < length; i++ ) {        //Only deal with non-null/undefined values        if(options = arguments[i])! =NULL ) {            //Extend the Base object             for(Nameinchoptions) {src=target[name]; Copy=options[name]; //Prevent Never-Ending Loop                if(target = = =copy) {                    Continue; }                //Recurse If we ' re merging plain objects or arrays                if(Deep && copy && jquery.isplainobject (copy) | | (Copyisarray =jquery.isarray (copy))) ) {                    if(Copyisarray) {Copyisarray=false; Clone= src && jquery.isarray (src)?src: []; } Else{Clone= src && jquery.isplainobject (src)?src: {}; }                    //never move original objects, clone themtarget[name] =jquery.extend (deep, clone, copy); //Don ' t bring in undefined values}Else if(Copy!==undefined) {target[name]=copy; }            }        }    }

This part is the core of this method, starting from the Arguements object's I subscript value start loop operation first filter out the source object is null or undefined situation can be seen in fact

The source object is not necessarily true to the image, it can be other types of values such as strings such as writing:

Console.log ($.extend ({' name ': ' Tom '}, ' AA '));   // Object {0: "A", 1: "A", Name: "Tom"}

Does it feel weird? How did it come true? Keep looking down.

After filtering, start the For Loop SRC holds the value of a key of the target object, and the Copy property holds the value of a key of the source object, both of which are the same

// Prevent never-ending Loop                if (target = = copy)                    {continue;                }

If a property value of the source object is a target object that could cause the program to crash due to a dead loop, there is a limit here to skip this loop for example:

var o ==true, O, {n2:o}); // Throw Exception: // uncaught rangeerror:maximum Call stack size exceeded

But doing so would also be an injustice to some normal situations such as:

var obj1={a: ' A 'var obj2={a:obj1}; Console.log ($.extend (OBJ1,OBJ2));//object {A : "A"}

This situation is also satisfied that the source object value equals the target object, but the result found Obj1 A's property value has not been modified, that is, because the execution of the continue, the following the source of this paragraph commented out in the execution

Object {A:object}

This time is normal has been modified personal feeling this place needs to be improved;

Then there is an if judgment is to distinguish whether deep copy is not first look at the depth of the copy of the general

target[name] = copy;

It is very simple that copy has a value directly copied to the target object, the target object has not been modified to increase, so that the implementation of the merger.

The For loop is returned after the new target object, so the target object is finally modified, and the result is the same as the returned result.

// Return the modified object    return target;
};

Now, let's talk about how deep replication is going to be handled.

The first thing to ensure that deep is true,copy has a value and is an object or an array (if it is not the object and the group depth copy is not discussed) and then the fractional groups and objects to deal with, first look at the case of the array:

if (Copyisarray) {         false;          = src && jquery.isarray (src)?  Else  {        = src && jquery.isplainobject (src)? src: {};}

If the value of the array Copyisarray is true then go inside the value of the change to false, for the current loop of the source object properties, the target object may or may not have, some words to determine whether the array is the original array is not the same thing, let it become an array, Since the current property of the source object is an array, the last destination element must also be an array. Not an array is an object that changes the target object's current property to an object.

    // never move original objects, clone them     target[name] = Jquery.extend (deep, clone, copy);

The current property value of the source object (which is an array or an object) and the current property of the target object that has been modified are then recursively merged and the new array or object that is returned is assigned to the target object, finally achieving deep replication.

But there's a strange phenomenon in this, like this:

      // Object {0: "A", 1: "A", a:1}

The original source object is not necessarily an object E and can actually take the string apart with the target object, the original for...in loop is the operation of the string

      var str= ' AA ';        for (var in str) {           console.log (name);         Console.log (Str[name])      }

This is also possible, the string will be taken apart by the digital subscript read, but in the source code

if (Deep && copy && jquery.isplainobject (copy) | | (Copyisarray = Jquery.isarray (copy))) )

There are arrays and object restrictions, so when the depth of the copy is not the effect of it?

After I test the depth of copy is also possible, because in the source code copy of the value turned into an anonymous function function

Alert (jquery.isplainobject (copy)); True

As to why the function of the author has not been clear to the future to solve it!

Jquery.extend () method and JQuery.fn.extend () method source code Analysis

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.