對(duì)象:
1. 對(duì)象中包含一系列的屬性儒拂,這些屬性是無序的悼枢。
2. 每個(gè)屬性都有一個(gè)字符串key和對(duì)應(yīng)的value脉课;(注:無論對(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ì)象屬性〔勺ぃ【js的原型鏈很重要,_ _proto_ _(隱式原型)是所有對(duì)象擁有的,prototype(顯示原型)是函數(shù)所擁有的,你每次new一個(gè)對(duì)象出來,都是調(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中是無法直接訪問的? 因?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__來表示: 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ì)象序列化