摘要:使用會(huì)遍歷所有的可枚舉屬性,包括原型。所以需要判斷一下,是否是對(duì)象自身的屬性,而不是繼承于原型的。注意,會(huì)跳過那些值為或的源對(duì)象。
代碼
var obj1 = {"a": "obj2","b":"2"}; var obj2 = {name: "obj3"}; function extend() { var length = arguments.length; var target = arguments[0] || {}; if (typeof target!="object" && typeof target != "function") { target = {}; } if (length == 1) { target = this; i--; } for (var i = 1; i < length; i++) { var source = arguments[i]; for (var key in source) { // 使用for in會(huì)遍歷數(shù)組所有的可枚舉屬性,包括原型。 if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; } console.log(extend(obj1,obj2));
extend 要實(shí)現(xiàn)的是給任意對(duì)象擴(kuò)展分析一下
在extend()函數(shù)中沒有寫死參數(shù),是為了更好的擴(kuò)展性,永遠(yuǎn)也不知道需要擴(kuò)展的對(duì)象有幾個(gè)。
而是通過arguments來獲取傳進(jìn)來的參數(shù)。
arguments對(duì)象不是一個(gè) Array 。它類似于Array,但除了length屬性和索引元素之外沒有任何Array屬性。
// 可以轉(zhuǎn)換為數(shù)組 ES2015 const args = Array.from(arguments); console.log(typeof arguments); // "object"target
target是傳進(jìn)來的第一個(gè)參數(shù),也就是需要擴(kuò)展的對(duì)象。
var target = arguments[0] || {}; // 如果沒有傳參,則設(shè)為一個(gè)空對(duì)象 // 進(jìn)行這一步判斷是為了保證代碼的可執(zhí)行性,如果傳進(jìn)來的是個(gè)數(shù)字、布爾值,則設(shè)為一個(gè)空對(duì)象 if (typeof target!="object" && typeof target != "function") { target = {}; }循環(huán)遍歷賦值
for (var i = 1; i < length; i++) { var source = arguments[i]; for (var key in source) { // 使用for in會(huì)遍歷數(shù)組所有的可枚舉屬性,包括原型。 if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } }
這一步就是將擴(kuò)展源里的屬性、方法循環(huán)遍歷賦值到擴(kuò)展項(xiàng)中。
如果擴(kuò)展項(xiàng)和擴(kuò)展源中有相同的屬性、方法,后面的會(huì)覆蓋前面的。 這個(gè)思想也是插件開發(fā)中,實(shí)現(xiàn)用戶配置覆蓋默認(rèn)設(shè)置的實(shí)現(xiàn)思想。hasOwnProperty
為什么需要使用hasOwnProperty,這跟for in有密切關(guān)系。
使用for in會(huì)遍歷所有的可枚舉屬性,包括原型。
所以需要判斷一下,是否是對(duì)象自身的屬性,而不是繼承于原型的。
那為什么不直接使用source.hasOwnProperty(source[key])呢?JavaScript 并沒有保護(hù) hasOwnProperty 屬性名,因此某個(gè)對(duì)象是有可能存在使用這個(gè)屬性名的屬性,使用外部的 hasOwnProperty 獲得正確的結(jié)果是需要的:
var foo = { hasOwnProperty: function() { return false; }, bar: "Here be dragons" }; foo.hasOwnProperty("bar"); // 始終返回 false // 如果擔(dān)心這種情況,可以直接使用原型鏈上真正的 hasOwnProperty 方法 ({}).hasOwnProperty.call(foo, "bar"); // true // 也可以使用 Object 原型上的 hasOwnProperty 屬性 Object.prototype.hasOwnProperty.call(foo, "bar"); // truecall apply
上面用到的call和apply,就在這里記錄一下。
1.每個(gè)函數(shù)都包含兩個(gè)非繼承而來的方法:call()方法和apply()方法。
2.相同點(diǎn):這兩個(gè)方法的作用是一樣的。
都是在特定的作用域中調(diào)用函數(shù),等于設(shè)置函數(shù)體內(nèi)this對(duì)象的值,以擴(kuò)充函數(shù)賴以運(yùn)行的作用域。
一般來說,this總是指向調(diào)用某個(gè)方法的對(duì)象,但是使用call()和apply()方法時(shí),就會(huì)改變this的指向。
3.不同點(diǎn):接收參數(shù)的方式不同。
apply()方法 接收兩個(gè)參數(shù),一個(gè)是函數(shù)運(yùn)行的作用域(this),另一個(gè)是參數(shù)數(shù)組。
語法:apply([thisObj [,argArray] ]);,調(diào)用一個(gè)對(duì)象的一個(gè)方法,2另一個(gè)對(duì)象替換當(dāng)前對(duì)象。
說明:如果argArray不是一個(gè)有效數(shù)組或不是arguments對(duì)象,那么將導(dǎo)致一個(gè)TypeError,如果沒有提供argArray和thisObj任何一個(gè)參數(shù),那么Global對(duì)象將用作thisObj。
call()方法 第一個(gè)參數(shù)和apply()方法的一樣,但是傳遞給函數(shù)的參數(shù)必須列舉出來。
語法:call([thisObject[,arg1 [,arg2 [,...,argn]]]]);,應(yīng)用某一對(duì)象的一個(gè)方法,用另一個(gè)對(duì)象替換當(dāng)前對(duì)象。
說明: call方法可以用來代替另一個(gè)對(duì)象調(diào)用一個(gè)方法,call方法可以將一個(gè)函數(shù)的對(duì)象上下文從初始的上下文改變?yōu)閠hisObj指定的新對(duì)象,如果沒有提供thisObj參數(shù),那么Global對(duì)象被用于thisObj。
// call window.name = "FinGet"; document.name = "FinGet1"; var boy = {name: "FinGet2" }; function showName(){ console.log(this.name); } showName.call(); //FinGet (默認(rèn)傳遞參數(shù)) this 是指向window showName.call(window); //FinGet showName.call(document); //FinGet1 showName.call(this); //FinGet showName.call(boy); //FinGet2 var Pet = { words : "hello", speak : function (say) { console.log(say + ""+ this.words) } } Pet.speak("Speak"); // 結(jié)果:Speakhello var Dog = { words:"Wang" } //將this的指向改變成了Dog Pet.speak.call(Dog, "Speak"); //結(jié)果: SpeakWang
可以將上面代碼中的call換成apply,也是可以執(zhí)行的。
Object.assignObject.assign(target, ...sources)
target 目標(biāo)對(duì)象
sources 源對(duì)象
如果目標(biāo)對(duì)象中的屬性具有相同的鍵,則屬性將被源中的屬性覆蓋。后來的源的屬性將類似地覆蓋早先的屬性。
注意,Object.assign 會(huì)跳過那些值為 null 或 undefined 的源對(duì)象。
var obj1 = {a:"1",b:"2"}; var obj2 = {c:"3",d:"4"}; Object.assign(obj1,obj2); // Object {a: "1", b: "2", c: "3", d: "4"} obj1 也改變 Object {a: "1", b: "2", c: "3", d: "4"} obj2 Object {c: "3", d: "4"}
更多相關(guān)Object.assign可以查看官網(wǎng)。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/94139.html
摘要:類的方法相當(dāng)于之前我們定義在構(gòu)造函數(shù)的原型上。的構(gòu)造函數(shù)中調(diào)用其目的就是調(diào)用父類的構(gòu)造函數(shù)。是先創(chuàng)建子類的實(shí)例,然后在子類實(shí)例的基礎(chǔ)上創(chuàng)建父類的屬性。 前言 首先歡迎大家關(guān)注我的Github博客,也算是對(duì)我的一點(diǎn)鼓勵(lì),畢竟寫東西沒法獲得變現(xiàn),能堅(jiān)持下去也是靠的是自己的熱情和大家的鼓勵(lì)?! ≡S久已經(jīng)沒有寫東西了,因?yàn)殡s七雜八的原因最近一直沒有抽出時(shí)間來把寫作堅(jiān)持下來,感覺和跑步一...
摘要:事件簡介事件是合成事件,所有事件都自動(dòng)綁定到最外層上。支持事件的冒泡機(jī)制,我們可以使用和來中斷它。這樣做簡化了事件處理和回收機(jī)制,效率也有很大提升。事件類型合成事件的事件類型是原生事件類型的一個(gè)子集。 React事件簡介 React事件是合成事件,所有事件都自動(dòng)綁定到最外層上。因?yàn)閂irtual DOM 在內(nèi)存中是以對(duì)象的形式存在的,所以React 基于 Virtual DOM 實(shí)現(xiàn)了...
摘要:事件簡介事件是合成事件,所有事件都自動(dòng)綁定到最外層上。支持事件的冒泡機(jī)制,我們可以使用和來中斷它。這樣做簡化了事件處理和回收機(jī)制,效率也有很大提升。事件類型合成事件的事件類型是原生事件類型的一個(gè)子集。 React事件簡介 React事件是合成事件,所有事件都自動(dòng)綁定到最外層上。因?yàn)閂irtual DOM 在內(nèi)存中是以對(duì)象的形式存在的,所以React 基于 Virtual DOM 實(shí)現(xiàn)了...
摘要:因?yàn)闊o法通過借用構(gòu)造函數(shù)的方式創(chuàng)建響應(yīng)式屬性雖然屬性可以被創(chuàng)建,但不具備響應(yīng)式功能,因此在我們是沒法繼承數(shù)組的。上面整個(gè)的文章都是基于監(jiān)聽數(shù)組響應(yīng)的一個(gè)點(diǎn)想到的。 前言 首先歡迎大家關(guān)注我的Github博客,也算是對(duì)我的一點(diǎn)鼓勵(lì),畢竟寫東西沒法獲得變現(xiàn),能堅(jiān)持下去也是靠的是自己的熱情和大家的鼓勵(lì)。 從上一篇文章響應(yīng)式數(shù)據(jù)與數(shù)據(jù)依賴基本原理開始,我就萌發(fā)了想要研究Vue源碼的想法...
摘要:使用新的易用的類定義,歸根結(jié)底也是要?jiǎng)?chuàng)建構(gòu)造函數(shù)和修改原型。首先,它把構(gòu)造函數(shù)當(dāng)成單獨(dú)的函數(shù)且包含類屬性集。該節(jié)點(diǎn)還儲(chǔ)存了指向父類的指針引用,該父類也并儲(chǔ)存了構(gòu)造函數(shù),屬性集和及父類引用,依次類推。 原文請查閱這里,略有刪減,本文采用知識(shí)共享署名 4.0 國際許可協(xié)議共享,BY Troland。 本系列持續(xù)更新中,Github 地址請查閱這里。 這是 JavaScript 工作原理的第...
閱讀 1074·2021-11-12 10:34
閱讀 999·2021-09-30 09:56
閱讀 676·2019-08-30 15:54
閱讀 2610·2019-08-30 11:14
閱讀 1476·2019-08-29 16:44
閱讀 3215·2019-08-29 16:35
閱讀 2500·2019-08-29 16:22
閱讀 2453·2019-08-29 15:39