Skip to content

[javascript] vanilla js 實作 JQuery.extend 方法

Published: at 05:32 AM (4 min read)

若有使用過 JQuery,或許會對 extend 這個方法有些熟悉及基本了解。


先來看看 extend 的用法

jQuery.extend(obja, objb) 方法輸入為兩個參數,此方法會判斷 obja 與 objb 屬性,將 objb 物件所擁有的屬性覆寫/新增至 obja,並回傳 obja。

來看看程式碼比較快理解~

[javascript]

var a = {

‘name’: ‘John’ };

var b = {

‘name’: ‘Marry’,

‘phone’: 0912345678

};

var c = jQuery.extend(a, b);

console.log(a); // { ‘name’: ‘Marry’, ‘phone’: 0912345678 }

console.log(b); // { ‘name’: ‘Marry, ‘phone’: 0912345678 }

console.log(a === b); // false

console.log(a === c); // true

console.log(b === c); //false

[/javascript]

從上面的例子可以發現幾個值得注意的地方

接下來,我們試著用 vanilla js 實作 extend 函式

[javascript] function extend(a, b) { for ( var prop in b ) { a[prop] = b[prop]; } return a; }

var a = {

‘name’: ‘John’ };

var b = {

‘name’: ‘Marry’,

‘phone’: 0912345678

};

var c = extend(a, b);

console.log(a); // { ‘name’: ‘Marry’, ‘phone’: 0912345678 }

console.log(b); // { ‘name’: ‘Marry, ‘phone’: 0912345678 }

console.log(a === b); // false

console.log(a === c); // true

console.log(b === c); //false [/javascript]

上面這段程式碼簡單實作了jQuery 基礎的 extend,但實際的 jquery.extend 提供更多的選項及參數彈性

舉例來說:

[code] function extend(a, b) { for ( var prop in b ) { a[prop] = b[prop]; } return a; } var a = { ‘second’: { ‘nest1’: 1 } }; var b = { ‘first’:1, ‘second’: { ‘nest2’: 2 } };

var c = extend(a, b); console.log(c); // {‘first’: 1, ‘second’: {‘nest2’:2}} [/code]

上面這段程式碼, a 與 b 物件皆有 second ,而且 second 底下的屬性是不相同的,但卻直接被覆寫。

也就是沒有 deep extend ( jquery.extend 中有一個 deep copy 的選項)

若是 deep copy 我們理論上會得到以下結果

[code] {‘first’: 1, ‘second’: {‘nest1’: 1, ‘nest2’:2}} [/code]

這部分使用 vanilla js 實作的程式碼就冗長了不少,完整程式碼附在下方

我想就不詳細解釋,大概提以下幾點

  1. 最重要的是利用遞迴的概念往下挖。(有學過 Tree 相關的資料結構應該懂XD)
  2. 第一個參數決定是否 deep,預設 false
  3. js function 內建的 arguments 去抓目前參數(因為第一個參數未必是 Object,可能是 deep)

[javascript]

function extend() { var extended = arguments[0]; var deep = false; var i = 0; var length = arguments.length;

if ( Object.prototype.toString.call( arguments[0] ) === ‘[object Boolean]’ ) { deep = arguments[0]; extended = arguments[1]; i++; } var merge = function (obj) { for ( var prop in obj ) { if ( Object.prototype.hasOwnProperty.call( obj, prop ) ) { if ( deep && Object.prototype.toString.call(obj[prop]) === ‘[object Object]’ ) { extended[prop] = extend( true, extended[prop], obj[prop] ); } else { extended[prop] = obj[prop]; } } } }; for ( ; i < length; i++ ) { var obj = arguments[i]; merge(obj); } return extended; } [/javascript]

參考資料:

https://gomakethings.com/vanilla-javascript-version-of-jquery-extend/