標籤:padding name nts 覆蓋 line obj 代碼 簡單的 變化
目錄
1 . jquery extend的基本使用
通過285行的源碼 jQuery.extend = jQuery.fn.extend = function() { ,extend方法要麼是直接掛在到jQuery的靜態方法,要麼是掛載到fn上其實就是原型上(參考283行的賦值操作)的執行個體方法。extend方法可以傳一個對象,類似於外掛程式的方式,也可以傳多個對象進行拷貝。
<script src="js/jquery-2.0.3.js"></script> <script> $.extend({ aaa:function(){ alert("1"); }, bbb:function(){ alert("2"); } }) $.fn.extend({ aaa:function(){ alert("3"); }, bbb:function(){ alert("4"); } }) $.aaa();//彈出1,靜態方法可以直接調用 $().aaa();//彈出3,綁定到fn上的方法,以對象的形式調用 //多個對象參數,後面的對象會擴充到第一個對象上 var a={}; $.extend(a,{color:‘#f40‘}); console.log(a);//color所在的對象就被擴充到a對象上 </script>
接下來關注extend的拷貝分深拷貝和淺拷貝。
<script src="js/jquery-2.0.3.js"></script> <script> var a={}; var b={name:"hello"}; var c={name:"hello-1"}; var d={name:{age:20}}; var e={name:{age:50}}; //淺拷貝對象b $.extend(a,b); a.name="hi"; alert(b.name);//彈出hello //淺拷貝對象d $.extend(a,d); a.name.age=30; alert(d.name.age);//彈出30 //深拷貝對象c $.extend(true,a,c); a.name="hi"; alert(c.name);//彈出hello-1 //深拷貝對象e $.extend(true,a,e); a.name.age=40; alert(e.name.age);//彈出50 </script>
2.代碼簡化版本
分為5個部分:
定義了一些變數
if(){} 是不是深拷貝
if(){} 參數正確不
if(){} 看是不是外掛程式的情況,外掛程式的話傳入一個含有方法的json對象
for 傳入多個對象的情況
if防止迴圈應用,if深拷貝,else if淺拷貝。
詳解篇:3.1 定義了一些變數
var options, name, src, copy, copyIsArray, clone, target = arguments[0] || {}, i = 1, length = arguments.length, deep = false;
這裡要說明一下target。它就是 $.extend(a,d); 拷貝的目標對象a。這裡的arguments是javascript的內建對象,是一個類數組,索引為0的值當然是參數a。
詳解篇:3.2 看是不是深拷貝
// 處理深拷貝的情形 if ( typeof target === "boolean" ) { deep = target; target = arguments[1] || {}; // 如果傳入的第一個參數為true,那麼deep就置為true了。target目標對象就調整為第二個。 //跳過布爾值和target i = 2; }
這裡處理的是傳入了true的情況,比如 $.extend(true,a,c); 。
詳解篇:3.3 要傳正確的的參數
// 如果傳進來的並非object同時也不是function,那麼target置為空白對象。 if ( typeof target !== "object" && !jQuery.isFunction(target) ) { target = {}; }
詳解篇:3.4 處理外掛程式的情形
// 如果傳進來一個參數,那麼target目標對象就為jquery自己。 if ( length === i ) { target = this; --i; }
詳解篇:3.5 傳入多個對象的操作
基本思路是通過arguments進行取值,擷取到每個非目標對象的參數。非target對象通過in迴圈,擷取到屬性名稱。
總體特徵是淺拷貝只能拷貝一層,深拷貝可以連嵌套子物件也能拷貝進去。
淺拷貝的情況下,那麼走的是else分支,對相應的值進行覆蓋 target[ name ] = copy; 。可以看到如果原來有target有相同的屬性,那麼就覆蓋,如果沒有,那麼就添加上。
<script src="js/jquery-2.0.3.js"></script> <script> var a={name:{age:20}}; var b={name:{age:50}}; //淺拷貝對象b $.extend(false,a,b); console.log(a);//{name:{age:20}} console.log(b);//{name:{age:50}} </script>
它遇到對象嵌套,copy這裡是{age:50},通過簡單的賦值是修改不了的。
<script> var a={name:{age:20}}; var b={name:{age:50}}; a[name]=b[name]; console.log(a);//{name:{age:20}},沒有變化哦。 </script>
深拷貝的情況下。copy是數組,src也為數組賦值給clone否則為空白數組。copy是對象,src是對象賦值給clone否則為空白對象。
<script src="js/jquery-2.0.3.js"></script> <script> var a={name:{age:20}}; var b={name:{age:50}}; //淺拷貝對象b $.extend(true,a,b); console.log(a);//{name:{age:50}} console.log(b);//{name:{age:50}} </script>
深拷貝的copy等於{age:50},src等於{age:20}。那麼通過複製的方式就可以把copy給到src。這其實是一個遞迴調用,所以深拷貝會拷貝到底。
for ( ; i < length; i++ ) { // 處理非空或者沒有定義的情況 if ( (options = arguments[ i ]) != null ) { // 擴充基礎對象,in文法把屬性值取出來 for ( name in options ) { src = target[ name ]; copy = options[ name ]; // 防止無限迴圈,類似$.extend(a,{name:a})。那麼如果拷貝的某一個值就等於target那麼就終止代碼在繼續迴圈 if ( target === copy ) { continue; } // 深拷貝和copy存在,以及copy要麼是對象、要麼是數組 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 : {}; } // 不移動原對象,複製他們。 target[ name ] = jQuery.extend( deep, clone, copy ); // Don‘t bring in undefined values } else if ( copy !== undefined ) { target[ name ] = copy; } } } }
jquery的2.0.3版本源碼系列(3):285-348行,extend方法詳解