javascript
JS-Object 对象的相关方法
參考文章:Object 對象的相關(guān)方法
1.Object.getPrototypeOf()
Object.getPrototypeOf方法返回參數(shù)對象的原型。這是獲取原型對象的標(biāo)準(zhǔn)方法。
- 下面代碼中,實(shí)例對象f的原型是F.prototype。
- 下面是幾種特殊對象的原型。
2.Object.setPrototypeOf()
- Object.setPrototypeOf方法為現(xiàn)有對象設(shè)置原型,返回該現(xiàn)有對象。它接受兩個參數(shù),第一個是現(xiàn)有對象,第二個是原型對象。
上面代碼中,Object.setPrototypeOf方法將對象a的原型,設(shè)置為對象b,因此a可以共享b的屬性。
- new命令可以使用Object.setPrototypeOf方法模擬。
上面代碼中,new命令新建實(shí)例對象,其實(shí)可以分成兩步:
第一步,將一個空對象的原型設(shè)為構(gòu)造函數(shù)的prototype屬性(上例是F.prototype),返回值為空對象{}賦值給變量f;
第二步,將構(gòu)造函數(shù)內(nèi)部的this綁定到這個空對象f,使得定義在this上面的方法和屬性(上例是this.foo),都轉(zhuǎn)移到這個空對象上。
3.Object.create()
生成實(shí)例對象的常用方法是,使用new命令讓構(gòu)造函數(shù)返回一個實(shí)例對象。但我們怎么從一個實(shí)例對象,生成另一個實(shí)例對象呢?
- JavaScript 提供了Object.create方法,用來滿足這種需求。該方法接受一個原型對象作為參數(shù),返回一個實(shí)例對象。該實(shí)例完全繼承原型對象的屬性。
上面代碼中,Object.create方法以A對象為原型,生成了B對象。B繼承了A的所有屬性和方法。
- 實(shí)際上,Object.create方法可以用下面的代碼代替。
上面代碼表明,Object.create方法的實(shí)質(zhì)是:
(1)新建一個空的構(gòu)造函數(shù)F,
(2)然后讓F.prototype屬性指向參數(shù)對象obj,
(3)最后返回一個F的實(shí)例,從而實(shí)現(xiàn)讓該實(shí)例繼承obj的屬性。
- 下面三種方式生成的新對象是等價的。
- 如果想要生成一個不繼承任何屬性(比如沒有toString和valueOf方法)的對象,可以將Object.create的參數(shù)設(shè)為null。
上面代碼中,對象obj的原型是null,它就不具備一些定義在Object.prototype對象上面的屬性,比如valueOf方法。
- 使用Object.create方法的時候,必須提供原型對象,即參數(shù)不能為空,或者不是對象,否則會報錯。
- Object.create方法生成的新對象,動態(tài)繼承了原型。在原型上添加或修改任何方法,會立刻反映在新對象之上。
上面代碼中,修改對象原型obj1會影響到實(shí)例對象obj2。
- 除了對象的原型,Object.create方法還可以接受第二個參數(shù)。該參數(shù)是一個屬性描述對象,它所描述的對象屬性,會添加到實(shí)例對象,作為該對象自身的屬性。
- Object.create方法生成的對象,繼承了它的原型對象的構(gòu)造函數(shù)。
上面代碼中,b對象的原型是a對象,因此b繼承了a對象的構(gòu)造函數(shù)A。
4.Object.prototype.isPrototypeOf()
實(shí)例對象的isPrototypeOf方法,用來判斷該對象是否為參數(shù)對象的原型。
var o1 = {}; var o2 = Object.create(o1); var o3 = Object.create(o2);o2.isPrototypeOf(o3) // true o1.isPrototypeOf(o3) // true 復(fù)制代碼上面代碼中,o1是o3**的原型,o2也是o3的原型。這表明只要實(shí)例對象處在參數(shù)對象的原型鏈上,isPrototypeOf方法都返回true。
Object.prototype.isPrototypeOf({}) // true Object.prototype.isPrototypeOf([]) // true Object.prototype.isPrototypeOf(/xyz/) // true Object.prototype.isPrototypeOf(Object.create(null)) // false 復(fù)制代碼上面代碼中,由于Object.prototype處于原型鏈的最頂端,所以對各種實(shí)例都返回true。只有直接繼承自null的對象除外。
5.Object.prototype.__proto__
實(shí)例對象的__proto__屬性(前后各兩個下劃線),返回該對象的原型。該屬性可讀寫。
- 下面代碼通過__proto__屬性,將p對象設(shè)為obj對象的原型。
-
根據(jù)語言標(biāo)準(zhǔn),__proto__屬性只有瀏覽器才需要部署,其他環(huán)境可以沒有這個屬性。它前后的兩根下劃線,表明它本質(zhì)是一個內(nèi)部屬性,不應(yīng)該對使用者暴露。因此,應(yīng)該盡量少用這個屬性,而是應(yīng)該用Object.getPrototypeof()和Object.setPrototypeOf(),進(jìn)行原型對象的讀寫操作。
-
原型鏈可以用__proto__很直觀地表示。
上面代碼中,A對象和B對象的原型都是proto對象,它們都共享proto對象的print方法。也就是說,A和B的print方法,都是在調(diào)用proto對象的print方法。
6.獲取原型對象方法的比較
如前所述,__proto__屬性指向當(dāng)前對象的原型對象,即構(gòu)造函數(shù)的prototype屬性。
var obj = new Object();obj.__proto__ === Object.prototype // true obj.__proto__ === obj.constructor.prototype // true 復(fù)制代碼上面代碼首先新建了一個對象obj,它的__proto__屬性,指向構(gòu)造函數(shù)(Object或obj.constructor)的prototype屬性。
- 因此,獲取實(shí)例對象obj的原型對象,有三種方法。
上面三種方法之中,前兩種都不可靠。
__proto__屬性只有瀏覽器才需要部署,其他環(huán)境可以不部署。
而obj.constructor.prototype在手動改變原型對象時,可能會失效。
下面代碼中,構(gòu)造函數(shù)C的prototype 被改成了p,但是實(shí)例對象c的構(gòu)造函數(shù)constructor的prototype卻沒有指向p。
var P = function () {}; var p = new P();var C = function () {}; C.prototype = p;//構(gòu)造函數(shù)C的prototype 被改成了p var c = new C();c.constructor.prototype === p // false 復(fù)制代碼所以,在改變原型對象時,一般要同時設(shè)置constructor屬性。
C.prototype = p; C.prototype.constructor = C;var c = new C(); c.constructor.prototype === p // true 復(fù)制代碼因此,推薦使用第三種Object.getPrototypeOf方法,獲取原型對象。
7.Object.getOwnPropertyNames()
Object.getOwnPropertyNames方法返回一個數(shù)組,成員是參數(shù)對象本身的所有屬性的鍵名,不包含繼承的屬性鍵名。
Object.getOwnPropertyNames(Date) // ["parse", "arguments", "UTC", "caller", "name", "prototype", "now", "length"] 復(fù)制代碼上面代碼中,Object.getOwnPropertyNames方法返回Date所有自身的屬性名。
對象本身的屬性之中,有的是可以遍歷的(enumerable),有的是不可以遍歷的。Object.getOwnPropertyNames方法返回所有鍵名,不管是否可以遍歷。Object.keys方法只獲取那些可以遍歷的屬性。
Object.keys(Date) // [] 復(fù)制代碼上面代碼表明,Date對象所有自身的屬性,都是不可以遍歷的。
8.Object.prototype.hasOwnProperty()
對象實(shí)例的hasOwnProperty方法返回一個布爾值,用于判斷某個屬性定義在對象自身,還是定義在原型鏈上。
Date.hasOwnProperty('length') // true Date.hasOwnProperty('toString') // false 復(fù)制代碼上面代碼表明,Date.length(構(gòu)造函數(shù)Date可以接受多少個參數(shù))是Date自身的屬性,Date.toString是繼承的屬性。
另外,hasOwnProperty方法是 JavaScript 之中唯一一個處理對象屬性時,不會遍歷原型鏈的方法。
9. in 運(yùn)算符和 for...in 循環(huán)
- in運(yùn)算符返回一個布爾值,表示一個對象是否具有某個屬性。它不區(qū)分該屬性是對象自身的屬性,還是繼承的屬性。
in運(yùn)算符常用于檢查一個屬性是否存在。
- 獲得對象的所有可遍歷屬性(不管是自身的還是繼承的),可以使用for...in循環(huán)。
上面代碼中,對象o2的p2屬性是自身的,p1屬性是繼承的。這兩個屬性都會被for...in循環(huán)遍歷。
- 為了在for...in循環(huán)中獲得對象自身的屬性,可以采用hasOwnProperty方法判斷一下。
- 獲得對象的所有屬性(不管是自身的還是繼承的,也不管是否可枚舉),可以使用下面的函數(shù)。
上面代碼依次獲取obj對象的每一級原型對象“自身”的屬性,從而獲取obj對象的“所有”屬性,不管是否可遍歷。
下面是一個例子,列出Date對象的所有屬性。
inheritedPropertyNames(Date) // [ // "caller", // "constructor", // "toString", // "UTC", // ... // ] 復(fù)制代碼10.對象的拷貝
如果要拷貝一個對象,需要做到下面兩件事情:
- 確??截惡蟮膶ο?#xff0c;與原對象具有同樣的原型。
- 確??截惡蟮膶ο?#xff0c;與原對象具有同樣的實(shí)例屬性。
下面就是根據(jù)上面兩點(diǎn),實(shí)現(xiàn)的對象拷貝函數(shù)。
function copyObject(orig) {var copy = Object.create(Object.getPrototypeOf(orig));copyOwnPropertiesFrom(copy, orig);return copy; }function copyOwnPropertiesFrom(target, source) {Object.getOwnPropertyNames(source).forEach(function (propKey) {//獲取源對象的屬性描述對象var desc = Object.getOwnPropertyDescriptor(source, propKey);//通過屬性描述對象desc,定義target對象上的屬性propKeyObject.defineProperty(target, propKey, desc);});return target; } 復(fù)制代碼另一種更簡單的寫法,是利用 ES2017 才引入標(biāo)準(zhǔn)的Object.getOwnPropertyDescriptors方法。
function copyObject(orig) {return Object.create(Object.getPrototypeOf(orig),//獲取orig對象的原型對象Object.getOwnPropertyDescriptors(orig)); } 復(fù)制代碼總結(jié)
以上是生活随笔為你收集整理的JS-Object 对象的相关方法的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: information_schema系列
- 下一篇: 在Docker中运行SpringBoot