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