【JavaScript】深入淺出JS對(duì)象

對(duì)象:

1. 對(duì)象中包含一系列的屬性,這些屬性是無(wú)序的。

2. 每個(gè)屬性都有一個(gè)字符串key和對(duì)應(yīng)的value;(注:無(wú)論對(duì)象的key是什么類型的,最后js都會(huì)默認(rèn)調(diào)用toString轉(zhuǎn)換成字符串類型)

3. 屬性是可以動(dòng)態(tài)添加和刪除的。(obj.x=1; obj.y=2;)

4. 對(duì)象結(jié)構(gòu),每個(gè)對(duì)象都有一個(gè)prototype的對(duì)象屬性?!緅s的原型鏈很重要,_ _proto_ _(隱式原型)是所有對(duì)象擁有的,prototype(顯示原型)是函數(shù)所擁有的,你每次new一個(gè)對(duì)象出來(lái),都是調(diào)用構(gòu)造函數(shù)(function既是函數(shù)也是對(duì)象),對(duì)象的_ _proto_ _就會(huì)指向構(gòu)造函數(shù)的prototype】(對(duì)象使用toString就是[object Object])

5. 屬性有g(shù)et/set方法,還有一些訪問權(quán)限的設(shè)置。writable 可寫?enumerable可枚舉? configurable可刪除? value值、等標(biāo)簽。這些標(biāo)簽是對(duì)對(duì)象屬性的權(quán)限操作。

6. 標(biāo)簽:①[[proto]]每個(gè)對(duì)象都有一個(gè)原型,如果在對(duì)象中沒有此屬性,就會(huì)一直沿著原型鏈查找②[[class]]表示對(duì)象屬于某類③[[extensible]]是否允許繼續(xù)增加新的屬性(這些標(biāo)簽屬于隱藏標(biāo)簽,在對(duì)象構(gòu)造中出現(xiàn),本身被賦予的值之外。)【這些標(biāo)簽是描述屬性特征的? 在js中是無(wú)法直接訪問的? 因?yàn)檫@些特性都是內(nèi)部值? ECMAScript的規(guī)范是把他們放在兩個(gè)方括號(hào)中的】


第1種創(chuàng)建對(duì)象方式-字面量:

var obj1 = {x : 1, y : 2};

/*對(duì)象值里嵌套對(duì)象*/ ?var obj2 = {x : 1,y : 2,o : {z : 3,n : 4}};

第2種創(chuàng)建對(duì)象方式,new 構(gòu)造器 的方式創(chuàng)建對(duì)象 / 原型鏈:

function foo(){}? (定義了一個(gè)函數(shù)對(duì)象,而該函數(shù)對(duì)象默認(rèn)就會(huì)有一個(gè)prototype屬性,而這個(gè)屬性是一個(gè)對(duì)象屬性)(每一個(gè)對(duì)象都有一個(gè) [[proto]]屬性)? foo.prototype.z = 3;? ? var obj =new foo();? ? obj.y = 2;? obj.x = 1; (函數(shù)的 [[proto]]原型屬性 會(huì)指向構(gòu)造器的prototype)

obj.x; // 1 ? obj.y; // 2 ? obj.z; // 3 ?typeof obj.toString; // ‘function' ? ?'z' in obj; // true ? ? ? obj.hasOwnProperty('z'); // false ? 備注:z不是obj對(duì)象上的,是prototype上的(父類繼承的)

對(duì)象賦值,不會(huì)向原型鏈上查找:obj.z = 5; ?先在對(duì)象本身上是否有z屬性,有直接修改,沒有在對(duì)象上添加z=5。如果在該對(duì)象創(chuàng)建了z,訪問就是創(chuàng)建的值,不再是原型鏈上的值。如果想要訪問原型鏈上的值,需要?jiǎng)h除本身創(chuàng)建的值。new原型鏈創(chuàng)建對(duì)象的方法能繼承原型鏈的值,但是不會(huì)修改原型鏈的值。

對(duì)象-->原型鏈prototype-->原型鏈末端object.prototype

原型鏈上的屬性 in --> true ; hasOwnPorperty() -->false

原型prototype:所有對(duì)象皆有的屬性,保存實(shí)例方法的真正所在。???不懂

原型鏈_proto_:指向構(gòu)造當(dāng)前對(duì)象的函數(shù)的prototype。終點(diǎn)是Object.prototype(指向null)有限原型鏈。

第3種創(chuàng)建對(duì)象方式,Object.create:

var obj = Object.create({x:1}); Object.create()是一個(gè)系統(tǒng)內(nèi)置的函數(shù),其參數(shù)通常為一個(gè)對(duì)象,該方法返回一個(gè)新創(chuàng)建的obj對(duì)象,并且該obj對(duì)象的原型指向這個(gè)參數(shù)對(duì)象,而參數(shù)對(duì)象原型指向Object.prototype。

例子如下:var obj = Object.create({x : 1});? ? obj.x // 1? ? (對(duì)象字面量創(chuàng)建的對(duì)象也是有原型的,它的原型指向object.prototype)( obj -> {x:1} -> Object.prototype -> null)

typeof obj.toString // "function" ? ? ? ?obj.hasOwnProperty('x');// false(繼承而非自己的)

并不是所有的對(duì)象都有.toString()方法,因?yàn)椴皇撬械膶?duì)象的原型鏈上都有Object.prototype屬性

例子如下:var obj = Object.create(null);? obj.toString // undefined? (它默認(rèn)也會(huì)有上一層的原型鏈object.prototype = null,但是如果直接負(fù)值 null 就沒有上一層的原型鏈了,因?yàn)閚ull沒有上一層原型鏈)


讀寫對(duì)象屬性:可以使用 點(diǎn).?操作符訪問屬性;也可以使用 [“” ] 訪問屬性,但其中 key 是字符串,就是不是字符串也會(huì)轉(zhuǎn)換為字符串。(拼屬性名的時(shí)候,會(huì)用到 [ ] ;)可以使用 for in 遍歷所有的屬性,但也會(huì)遍歷原型鏈上的屬性,而且,順序是不確定的。

屬性異常:訪問不存在的屬性,查遍原型鏈之后還是沒有就會(huì)返回undefined ; 寫異常是 看看該對(duì)象是否有,如果有就修改,如果沒有就重新賦值。但如果是給一個(gè)不存在的對(duì)象的屬性,再進(jìn)行屬性賦值的話,就不OK了。( if 檢測(cè)可以用 運(yùn)算符 & ,從左向右的查找

刪除屬性:delete . 或者 [ ] ,返回true 就表示刪除成功。重復(fù)對(duì)一個(gè)不存在的屬性進(jìn)行刪除,js依然會(huì)返回true。同意表明該對(duì)象不存在了,而不表示該操作生效 or 成功了。有些屬性不允許被刪除,比如Object.prototype,如果用 delete ,就會(huì)返回 false。var descriptor = ?Object.getOwnPropertyDescriptor(Object, 'prototype'); ?(屬性描述器,兩個(gè)參數(shù),一個(gè)是對(duì)象,一個(gè)是屬性)descriptor.configurable; // false(屬性為描述器,也是一個(gè)對(duì)象,不可配置)var 定義的全局對(duì)象或者局部對(duì)象也不能被刪除;函數(shù)聲明也不能被刪除。隱身創(chuàng)建的全局變量就可以被刪除。但eval()中創(chuàng)建的var 變量可以delete刪除呢。

檢測(cè)屬性:var cat = new Object;in 、 hasOwnProperty 、 propertyIsEnumerable。Object.defineProperty(cat, ‘price’, {enumerable : false, value : 1000});//參數(shù)為:屬性對(duì)象,屬性名字,對(duì)象;對(duì)象里可以設(shè)置標(biāo)簽,默認(rèn)時(shí)enumerable : false,writable=false, configurable=false。注意:用字面量、new創(chuàng)建的對(duì)象enumerable:true。 !==undefined or !==null ?-> !=undefined.

枚舉屬性:for in 是枚舉出對(duì)象及原型鏈上的屬性。原型鏈上toString不可以枚舉,只輸出x,y,z。若要輸出該對(duì)象的屬性,就增加obj.hasOwnProperty(key) 判斷,就可以只輸出obj對(duì)象上的屬性值了。


getter setter方法讀寫屬性

get 屬性名(){ } ,set 屬性名 (參數(shù)) { } ,(普通屬性是以冒號(hào)的方式分開 key 和value,而這種屬性是可以 get set 開頭,加上屬性名 ……)(val = +val 是用一元加號(hào)符把字符串轉(zhuǎn)換成數(shù)字,如果是數(shù)字就什么也不做。)!isNaN 是不等于NaN? ? $age : null, //$age代表僅此對(duì)象能訪問。

defineProperty() 默認(rèn)writable configurable 為false。如果對(duì)象上沒有某個(gè)屬性,添加這個(gè)屬性時(shí),若原型鏈上有g(shù)et/set方法,就不會(huì)像之前那樣,在對(duì)象上直接修改或刪除 這個(gè)屬性。

var a = new Object();? //a的原型指向Object.prototype,a是沒有prototype的,在chrome中a的原型用__proto__來(lái)表示: a.__proto__ ===Object.prototype;? //true (1.原型鏈上有g(shù)et或set方法,就不會(huì)在當(dāng)前對(duì)象上設(shè)置元素。2.原型上有set方法,則對(duì)原型上屬性的賦值可以進(jìn)行,否則不行。)

var foo = {}; ? ?foo.x = 1; ? ?var obj = Object.create(foo); ? ? obj.x = 2; ? ? ?//這里能給予賦值是很正確的,可以通俗理解為obj和foo都是普通對(duì)象,普通對(duì)象當(dāng)然能給自己添加屬性賦值 ? //只是obj這個(gè)家伙偷懶‘引用’了foo的屬性。但不影響obj有權(quán)利隨意給自己添加屬性不受你foo的限制,//所以obj.x可以隨意賦值,但注意其實(shí)這沒有改變foo.x的值。

var foo = {}; ? ?Object.defineProperty(foo,'x',{value:1}); ? var obj = Object.create(foo); ?//這里就不一樣了,Object.defineProperty()就是皇上的圣旨,給了foo特權(quán),這個(gè)特權(quán)就是obj必須服從foo的指揮,只要foo說x是什么樣子,那obj的x就是什么樣子,所以這里不管obj.x賦值是多少對(duì)不起你都和foo.x的值一樣;


屬性標(biāo)簽:

.getOwnPropertyDescriptor(對(duì)象,需要字符串的屬性名) 可以返回對(duì)象上的標(biāo)簽 ? value 默認(rèn)值 writable 是否可以寫? enumerable屬性是否可以遍歷 被枚舉(for in 是否會(huì)出現(xiàn))? configurable(前面的屬性是否還可以再修改,是否可以delete刪除屬性) ?。 defineProperty(添加的對(duì)象,字符串屬性名,標(biāo)簽的值)創(chuàng)建屬性


對(duì)象標(biāo)簽、對(duì)象序列化

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容