對(duì)象中包含一系列屬性,這些屬性是無(wú)序的。每個(gè)屬性都有一個(gè)字符串key和對(duì)應(yīng)的value散怖。
JavaScript 對(duì)象概述
概述
對(duì)象中包含一系列屬性喷兼,這些屬性是無(wú)序的篮绰。每個(gè)屬性都有一個(gè)字符串key和對(duì)應(yīng)的value。
var obj = {x : 1, y : 2}; //定義obj對(duì)象季惯, 有兩個(gè)屬性x和y
obj.x; // 1 //訪問(wèn)對(duì)應(yīng)obj.x屬性取到對(duì)應(yīng)的值
obj.y; // 2 //訪問(wèn)對(duì)應(yīng)obj.y屬性取到對(duì)應(yīng)的值
這里有兩個(gè)重點(diǎn)吠各,一個(gè)是屬性是無(wú)序的,再一個(gè)每一個(gè)key
是字符串勉抓。
探索對(duì)象的key
var obj = {}; //定義對(duì)象obj
obj[1] = 1; //動(dòng)態(tài)賦值數(shù)字1屬性值為1
obj['1'] = 2; //動(dòng)態(tài)賦值字符串1屬性值為2
console.log(obj); // Object {1: 2} //實(shí)際上結(jié)果指向的是同一個(gè)屬性
//每個(gè)屬性都有一個(gè)字符串key和對(duì)應(yīng)的value贾漏。
obj[{}] = true; //[{}] 空對(duì)象作為key
obj[{x : 1}] = true; //對(duì)象帶有屬性的對(duì)象作為key //js都會(huì)把它轉(zhuǎn)換成字符串然后再去處理,最終指向的是同一個(gè)屬性
console.log(obj)// Object {1: 2, [object Object]: true}
回顧-數(shù)據(jù)類型
函數(shù)藕筋,數(shù)組纵散,日期,正則等都是對(duì)象
對(duì)象結(jié)構(gòu)
var obj = {}; //字面量空對(duì)象
obj.y = 2; //賦值創(chuàng)建屬性x
obj.x = 1; //賦值創(chuàng)建屬性y
對(duì)象有個(gè)特點(diǎn)隐圾,他的屬性可以動(dòng)態(tài)的添加或刪除的
函數(shù)對(duì)象
function foo(){};
console.log(foo.prototype);
創(chuàng)建一個(gè)函數(shù)聲明
每一個(gè)函數(shù)都會(huì)有一個(gè)foo.prototype
對(duì)象屬性
function foo(){};
foo.prototype.z=1;
console.log(foo.prototype);
給foo.prototype
對(duì)象屬性添加屬性z
賦值為1伍掀,foo.prototype
對(duì)象屬性下有個(gè)constructor
屬性方法,該屬性其實(shí)是指向自己本身暇藏。
function foo(){};
foo.prototype.z=1;
console.log(foo.prototype);
var obj =new foo();
console.log(obj);
通過(guò)new
去實(shí)例化foo()
函數(shù)var obj =new foo();
那么這個(gè)obj
原型就會(huì)指向構(gòu)造器的prototype
屬性也就是foo.prototype
硕盹,可以通過(guò)上圖看出打印輸出是一樣的。
JavaScript 創(chuàng)建對(duì)象叨咖,原型鏈
對(duì)象創(chuàng)建-字面量
var obj1 = {x : 1, y : 2};
對(duì)象字面量 瘩例,用{}設(shè)置屬性
var obj2 = {
x : 1,
y : 2,
o : {
z : 3,
n : 4
}
};
對(duì)象字面量也可以做一些嵌套啊胶,比如某些屬性值可以又是對(duì)象
創(chuàng)建對(duì)象-new/原型鏈
還有一種就是使用new
構(gòu)造器的方法創(chuàng)建對(duì)象,先來(lái)了解javascript中的原型鏈垛贤。
什么是原型鏈
function foo(){} //定義函數(shù)對(duì)象
foo.prototype.z = 3; //函數(shù)對(duì)象默認(rèn)帶foo.prototype對(duì)象屬性 對(duì)象添加z屬性=3
var obj =new foo(); //用構(gòu)造器方式構(gòu)造新的對(duì)象
obj.y = 2; //通過(guò)賦值添加2個(gè)屬性給obj
obj.x = 1; //通過(guò)new去構(gòu)造這樣一個(gè)對(duì)象他的主要特點(diǎn)是焰坪,他的原型會(huì)指向構(gòu)造器的foo.prototype屬性
obj.x; // 1 //訪問(wèn)obj.x發(fā)現(xiàn)對(duì)象上有x返回1
obj.y; // 2 //訪問(wèn)obj.y發(fā)現(xiàn)對(duì)象上有x返回2
obj.z; // 3 //obj上沒(méi)有z并不會(huì)停止查找,會(huì)去查找他的原型foo.prototype.z返回3
typeof obj.toString; // ‘function' 這是一個(gè)函數(shù)聘惦,toString是Object.prototype上面的每個(gè)對(duì)象都有
'z' in obj; // true obj.z是從foo.prototype繼承而來(lái)的某饰,所以說(shuō)obj里面有z
obj.hasOwnProperty('z'); // false 表示z并不是obj直接對(duì)象上的,而是對(duì)象原型鏈上的善绎。
但是如果是賦值的話結(jié)果就一樣了黔漂。
比如我們賦值obj.z=5
如果給obj.z
嘗試去賦值,就不會(huì)像原型鏈上去查找了禀酱。先看obj.z
有沒(méi)有炬守,有的話修改它的值,沒(méi)有的話剂跟,在對(duì)象上添加obj.z
减途。
obj.z = 5;
obj.hasOwnProperty('z'); // true
foo.prototype.z; // still 3
obj.z; // 5
obj.z = undefined;
obj.z; // undefined
那么怎樣能拿到原型鏈上的z呢
delete obj.z; // true 刪除對(duì)象上的z屬性
obj.z; // 3 //這樣就能獲取原型鏈上的z
對(duì)象創(chuàng)建-Object.create
從字面量理解是對(duì)象創(chuàng)建
Object.create({x:1});
是系統(tǒng)內(nèi)置的函數(shù),這個(gè)函數(shù)會(huì)接收一個(gè)參數(shù)曹洽,一般是一個(gè)對(duì)象鳍置。他會(huì)返回一個(gè)新創(chuàng)建的對(duì)象,并且讓這個(gè)對(duì)象的原型指向參數(shù)送淆,參數(shù)一般是個(gè)對(duì)象税产。
var obj = Object.create({
x: 1
});
console.log(obj.x) // 1
console.log(typeof obj.toString) // "function"
console.log(obj.hasOwnProperty('x')); // false
console.dir(obj)
JavaScript 屬性操作
讀寫(xiě)對(duì)象屬性
var obj = {
x: 1,
y: 2
};
console.log(obj.x); // 1
console.log(obj["y"]); // 2
obj["x"] = 3;
obj.y = 4;
創(chuàng)建對(duì)象字面量obj
,有x
和y
兩個(gè)屬性偷崩,可以用obj.y
(點(diǎn))操作符去訪問(wèn)他的屬性砖第,也可以用obj["y"]
[中括號(hào)這里需要是字符串]
var obj = {
x1: 1,
x2: 2
};
var i = 1,
n = 2;
for (; i <= n; i++) {
console.log(obj['x' + i]);
}
// 輸出: 1, 2
obj['x']使用方法,obj['x']同等于obj.x环凿。obj['x']可以在[]內(nèi)拼接字符串梧兼,obj.x+""不是那么方便
var obj = {
x1: 1,
x2: 2
};
var p;
for (p in obj) {
console.log(obj[p]);
}
用for...in遍歷所有屬性
需要注意的是用for...in
去遍歷的話,有可能把原型鏈上的屬性也遍歷出來(lái)智听,并且他的順序是不確定的羽杰。
屬性讀寫(xiě)-異常
var obj = {
x: 1
};//創(chuàng)建對(duì)象obj
console.log(obj.y); //如果訪問(wèn)一個(gè)不存在的屬性會(huì)進(jìn)行原型鏈查找如果找到末端還是找不到就會(huì)返回 undefined
var yz = obj.y.z; //不能獲取undefined的屬性z TypeError: Cannot read property 'z' of undefined
obj.y.z = 2; //不能給undefined的屬性z去賦值 TypeError: Cannot set property 'z' of undefined
var yz;
if (obj.y) {
yz = obj.y.z;
}//判斷當(dāng)obj.y存在把他取出來(lái)
//巧用運(yùn)算符
var yz = obj && obj.y && obj.y.z;
屬性刪除
var person = {
age: 28,
title: 'fe'
};
delete person.age; // true 表示刪除成功
delete person['title']; // true 表示刪除成功
person.age; // undefined
delete person.age; // true
delete Object.prototype; // false, 不允許刪除
//通過(guò)getOwnPropertyDescriptor方法去獲取一個(gè)屬性中所有的標(biāo)簽,第一個(gè)參數(shù)是你要查看的對(duì)象到推,第二個(gè)是你要去檢測(cè)的屬性這樣就能拿到屬性的描述器
var descriptor = Object.getOwnPropertyDescriptor(Object, 'prototype');
console.log(descriptor);
屬性檢測(cè)
var cat = new Object; //使用new 構(gòu)造對(duì)象
cat.legs = 4; //賦值屬性legs值為4
cat.name = "Kitty"; //賦值屬性name值為Kitty
'legs' in cat; // true 表示cat中有l(wèi)egs屬性 in操作符是會(huì)向原型鏈上查找的
'abc' in cat; // false 表示cat中沒(méi)有abc屬性
"toString" in cat; // true, 繼承 property有toString屬性
cat.hasOwnProperty('legs'); // true 表示cat直接量屬性有l(wèi)egs
cat.hasOwnProperty('toString'); // false 表示cat直接量屬性沒(méi)有toString toString是在原型有
cat.propertyIsEnumerable('legs'); // true legs可枚舉 查看是否可枚舉propertyIsEnumerable for...in會(huì)被循環(huán)
cat.propertyIsEnumerable('toString'); // false toString不可枚舉 查看是否可枚舉propertyIsEnumerable for...in不會(huì)被循環(huán)
自定義對(duì)象屬性考赛,讓他的枚舉標(biāo)簽是false
var cat = new Object; //使用new 構(gòu)造對(duì)象
cat.legs = 4; //賦值屬性legs值為4
cat.name = "Kitty"; //賦值屬性name值為Kitty
'legs' in cat; // true 表示cat中有l(wèi)egs屬性 in操作符是會(huì)向原型鏈上查找的
'abc' in cat; // false 表示cat中沒(méi)有abc屬性
"toString" in cat; // true, 繼承 property有toString屬性
cat.hasOwnProperty('legs'); // true 表示cat直接量屬性有l(wèi)egs
cat.hasOwnProperty('toString'); // false 表示cat直接量屬性沒(méi)有toString toString是在原型有
cat.propertyIsEnumerable('legs'); // true legs可枚舉 查看是否可枚舉propertyIsEnumerable for...in會(huì)被循環(huán)
cat.propertyIsEnumerable('toString'); // false toString不可枚舉 查看是否可枚舉propertyIsEnumerable for...in不會(huì)被循環(huán)
//通過(guò)Object.defineProperty給cat目標(biāo)對(duì)象去添加一個(gè)屬性price
//enumerable:是否能在for...in循環(huán)中遍歷出來(lái)或在Object.keys中列舉出來(lái)。
//value:屬性的值給屬性賦值
Object.defineProperty(cat, 'price', {enumerable: false, value: 1000});
cat.propertyIsEnumerable('price'); // false price不可枚舉 查看是否可枚舉propertyIsEnumerable for...in不會(huì)被循環(huán)
cat.hasOwnProperty('price'); // true 表示cat直接量屬性有price
console.log(cat)
for(var k in cat){
console.log(cat[k]);//循環(huán)出來(lái)看看能不能被枚舉
}
判斷對(duì)象屬性是否存在進(jìn)行操作
if (cat && cat.legs) {
cat.legs *= 2;
}//8
判斷cat
是否存在且cat.legs
不是undefined
的時(shí)候莉测,讓cat.legs
值乘等于2颜骤,表示cat.legs
乘以2再賦值給cat.legs
if (cat.legs !== undefined) {
// only if cat.legs is not undefined
}
判斷cat.legs
不等于undefined
的時(shí)候去做動(dòng)作
if (cat.legs !== undefined) {
// only if cat.legs is not undefined
}
判斷cat.legs
嚴(yán)格不等于undefined
的時(shí)候去做動(dòng)作
屬性枚舉
var o = {
x: 1,
y: 2,
z: 3
};
'toString' in o; // true
o.propertyIsEnumerable('toString'); // false
var key;
for (key in o) {
console.log(key); // x, y, z
}
這樣寫(xiě)出來(lái)的對(duì)象原型鏈屬性默認(rèn)是不可枚舉的,所以for....in
的時(shí)候原型鏈不會(huì)出來(lái)捣卤。
var o = {
x: 1,
y: 2,
z: 3
};
var obj = Object.create(o); //創(chuàng)建obj對(duì)象以o對(duì)象作為原型
obj.a = 4;
console.log(obj)
var key;
for (key in obj) {
console.log(key); // a, x, y, z
}
創(chuàng)建obj
對(duì)象以o
對(duì)象作為原型
所有對(duì)象上的屬性忍抽,和原型上的屬性都會(huì)遍歷中顯示出來(lái)
那有時(shí)候我只想處理對(duì)象上的屬性八孝,不想遍歷我對(duì)象原型鏈上的屬性。
我們需要在加一個(gè)obj.hasOwnProperty(key)
的判斷鸠项,來(lái)過(guò)濾掉原型鏈上的屬性就可以了干跛。
var o = {
x: 1,
y: 2,
z: 3
};
var obj = Object.create(o); //創(chuàng)建obj對(duì)象以o對(duì)象作為原型
obj.a = 4;
var key;
for (key in obj) {
if (obj.hasOwnProperty(key)){
console.log(key); // a
}
}
JavaScript get/set方法
JavaScript get/set方法
var man = {
name: 'huang',
weibo: '@.com',
get age() {
return new Date().getFullYear() - 1993;
},
set age(val) {
console.log('年齡不能設(shè)置' + val);
}
}
console.log(man.age); //23
man.age = 100; //年齡不能設(shè)置100
console.log(man.age); //23
定義了一個(gè)對(duì)象man
有屬性name
值是huang
,這里定義了一對(duì)get
和set
方法祟绊,來(lái)去訪問(wèn)屬性age
語(yǔ)法
用get
或set
關(guān)鍵字開(kāi)頭楼入,空格,然后是屬性的名字牧抽,然后是括號(hào)再方括號(hào)嘉熊,里面是一個(gè)函數(shù)體,
get
方法會(huì)返回當(dāng)前日期的年份減去我的出生日扬舒,會(huì)拿到我的年齡阐肤。
set
方法會(huì)拿到括號(hào)賦值的值,唯一的參數(shù)創(chuàng)進(jìn)來(lái)呼巴。
當(dāng)訪問(wèn)console.log(man.age); //23
會(huì)返回get
方法,
當(dāng)使用man.age = 100;
也就是說(shuō)給set
去賦值的時(shí)候御蒲,就會(huì)去調(diào)用set
方法衣赶,就會(huì)輸出年齡不能設(shè)置100
再去輸出console.log(man.age); //23
會(huì)發(fā)現(xiàn)仍然是23,因?yàn)?code>set沒(méi)做任何的事情厚满。
var man = {
name: 'huang',
$age: null,
get age() {
if (this.$age == undefined) {
return new Date().getFullYear() - 1993;
} else {
return this.$age;
}
},
set age(val) {
val = +val;
if (!isNaN(val) && val > 0 && val < 150) {
this.$age = +val;
} else {
throw new Error('Incorrect=' + val);
}
}
}
console.log(man.age); //23
man.age = 100;
console.log(man.age); //100
man.age = 'abn';
console.log(man.age);//Uncaught Error: Incorrect=NaN(…)
get/set與原型鏈
function foo() {};
Object.defineProperty(foo.prototype, 'z', {
get: function() {
return 1;
}
});
var obj = new foo();
console.log(obj.z); //1
obj.z = 10;
console.log(obj.z); //還是輸出1
Object.defineProperty(obj, 'z', {
value: 100,
configurable: true
});
console.log(obj.z);//100
delete obj.z;
console.log(obj.z);//1
解釋
function foo() {};
創(chuàng)建一個(gè)foo函數(shù)
府瞄,就會(huì)有一個(gè)foo.prototype
Object.defineProperty(foo.prototype, 'z', {
get: function() {
return 1;
}
});
通過(guò)defineProperty
用git
方法來(lái)創(chuàng)建z屬性
,git
方法只是固定的返回1碘箍。
var obj = new foo();
使用new
方式來(lái)創(chuàng)建一個(gè)新的對(duì)象obj
遵馆,這樣這個(gè)obj
對(duì)象的原型會(huì)指向foo.prototype
console.log(obj.z); //1
當(dāng)我們?nèi)ピL問(wèn)obj.z
的時(shí)候obj
對(duì)象上沒(méi)有z直接量屬性
,所以他會(huì)向上去查找丰榴,foo.prototype
原型货邓,發(fā)現(xiàn)有一個(gè)z屬性
用的是get
方法,這樣就能返回1四濒,
obj.z = 10;
console.log(obj.z); //還是輸出1
那么我賦值换况,嘗試給z
賦值為10,如果z不是用get方式賦值的是通過(guò)foo.prototype.z
原型賦值的話盗蟆,再使用直接量去賦值是可以成功的戈二,值會(huì)返回到obj
這個(gè)對(duì)象上,但是在這里賦值并沒(méi)有成功喳资。仍然返回1觉吭。
這是因?yàn)楫?dāng)obj
對(duì)象上沒(méi)有z直接量屬性的時(shí)候,并且他的原型鏈查找發(fā)現(xiàn)有get
和set
方法的時(shí)候仆邓,那么當(dāng)我們嘗試去賦值的時(shí)候鲜滩,實(shí)際上會(huì)走原型上get
和set
方法的伴鳖,而不會(huì)再去通過(guò)給當(dāng)前對(duì)象obj
添加新屬性。
Object.defineProperty(obj, 'z', {
value: 100,
configurable: true
});
通過(guò)Object.defineProperty
給obj
目標(biāo)對(duì)象去添加一個(gè)屬性z
- value:屬性的值給屬性賦值
- writable:如果為false绒北,屬性的值就不能被重寫(xiě)黎侈。
- get: 一旦目標(biāo)屬性被訪問(wèn)就會(huì)調(diào)回此方法,并將此方法的運(yùn)算結(jié)果返回用戶闷游。
- set:一旦目標(biāo)屬性被賦值峻汉,就會(huì)調(diào)回此方法。
- configurable:如果為false脐往,則任何嘗試刪除目標(biāo)屬性或修改屬性以下特性(writable, configurable, enumerable)的行為將被無(wú)效化休吠。
- enumerable:是否能在for...in循環(huán)中遍歷出來(lái)或在Object.keys中列舉出來(lái)。
console.log(obj.z);//100
這個(gè)時(shí)候obj.z是obj
的直接量返回100
delete obj.z;
由于configurable: true
所以刪除是成功的
console.log(obj.z);//1
這里因?yàn)橹苯恿縵被刪除們說(shuō)以他會(huì)繼續(xù)去向上查找z
的get
方法业簿。
小案例
var o={z:2};
Object.defineProperty(o,'x',{value:1});//默認(rèn)writable=false只讀,configurable=false不可寫(xiě)
o.z=6;
o.x=6;
console.log(o);
案例解釋
var o={};
Object.defineProperty(o,'x',{value:1});//默認(rèn)writable=false只讀,configurable=false不可寫(xiě)
var obj=Object.create(o);//創(chuàng)建obj對(duì)象以o對(duì)象作為原型
console.log(obj.x);//1 會(huì)向上查找返回原型鏈x屬性值1
obj.x=200; //嘗試去賦值200
console.log(obj.x);//賦值后打印任然是1
//那么如何去在obj對(duì)象添加x屬性呢瘤礁?
//還是要用Object.defineProperty
//給obj對(duì)象添加一個(gè)自己的屬性x,這樣就可以覆蓋掉原型鏈上的不可寫(xiě)的x梅尤,writable:true,configurable:true,value:100
Object.defineProperty(obj,'x',{writable:true,configurable:true,value:100});
console.log(obj.x);//100 obj.x是直接量屬性
obj.x=500; //直接量屬性可以賦值
console.log(obj.x);//500 //修改成功
JavaScropt屬性標(biāo)簽
屬性標(biāo)簽
怎樣去看某一個(gè)對(duì)象上的屬性上都有哪些標(biāo)簽
console.log(Object.getOwnPropertyDescriptor({pro:true}, 'pro'));檢查一個(gè)字面量的對(duì)象柜思,添加屬性`pro:true`看字面量下的屬性`pro`的屬性標(biāo)簽
//configurable:true,enumerable:true,value:true,writable:true
console.log(Object.getOwnPropertyDescriptor({pro:true}, 'a'));//去查一個(gè)根本不存在的屬性返回undefined
//undefined
通過(guò)Object.getOwnPropertyDescriptor(參數(shù)1,"參數(shù)2")
方法可以返回一個(gè)對(duì)象,這個(gè)對(duì)象上會(huì)顯示 當(dāng)前這個(gè)屬性下所有的標(biāo)簽巷燥,這個(gè)函數(shù)會(huì)接收兩個(gè)參數(shù)赡盘,第一個(gè)是你要去判斷的對(duì)象,第二個(gè)是一個(gè)字符串的屬性名缰揪,
- value:屬性的值給屬性賦值
- writable:如果為false陨享,屬性的值就不能被重寫(xiě)。
- get: 一旦目標(biāo)屬性被訪問(wèn)就會(huì)調(diào)回此方法钝腺,并將此方法的運(yùn)算結(jié)果返回用戶抛姑。
- set:一旦目標(biāo)屬性被賦值,就會(huì)調(diào)回此方法艳狐。
- configurable:如果為false定硝,則任何嘗試刪除目標(biāo)屬性或修改屬性以下特性(writable, configurable, enumerable)的行為將被無(wú)效化。
- enumerable:是否能在for...in循環(huán)中遍歷出來(lái)或在Object.keys中列舉出來(lái)
console.log(Object.getOwnPropertyDescriptor({pro:true}, 'pro'));檢查一個(gè)字面量的對(duì)象毫目,添加屬性`pro:true`看字面量下的屬性`pro`的屬性標(biāo)簽
得到的結(jié)果是
//configurable:true,enumerable:true,value:true,writable:true
那么怎么去設(shè)置或者說(shuō)設(shè)置對(duì)象的屬性標(biāo)簽?zāi)兀?/strong>
var person = {};
Object.defineProperty(person, 'name', {
configurable: false,
writable: false,
enumerable: false,
value: "繼小鵬"
});
console.log(person.name); //繼小鵬
person.price = 100; //修改不了
console.log(person.name); //還是繼小鵬
console.log(delete person.name); //false 不可刪除
解釋例子
創(chuàng)建一個(gè)空對(duì)象
var person = {};
通過(guò)Object.defineProperty(參數(shù)1,"參數(shù)2",{參數(shù)1})
第一個(gè)參數(shù)是要添加屬性的對(duì)象喷斋,第二個(gè)參數(shù)是一個(gè)字符串屬性的名字,第三個(gè)參數(shù)是一個(gè)對(duì)象蒜茴,這個(gè)對(duì)象里面就是具體每一個(gè)標(biāo)簽的值星爪,
Object.defineProperty(person, 'name', {
configurable: false,//不可刪除
writable: false,//屬性的值就不能被重寫(xiě)。
enumerable: true,//可枚舉
value: "繼小鵬"http://屬性的值給屬性賦值
});
結(jié)果符合預(yù)期
console.log(person.name); //繼小鵬
person.price = 100; //修改不了
console.log(person.name); //還是繼小鵬
console.log(delete person.name); //false 不可刪除
創(chuàng)建新的屬性使用Object.keys
var person = {};
Object.defineProperty(person, 'name', {
configurable: false,
writable: false,
enumerable: true,
value: "繼小鵬"
});
Object.defineProperty(person, 'type', {
configurable: true,
writable: true,
enumerable: false,
value: "繼小鵬222"
});
console.log(person);
console.log(Object.keys(person));
新創(chuàng)建的屬性enumerable: false,
不可枚舉粉私,可以通過(guò)Object.keys(person)
的方法來(lái)去獲取對(duì)象上所有的key
因?yàn)樾聞?chuàng)建的屬性enumerable: false,
不可枚舉所有不可見(jiàn)顽腾。
使用Object.defineProperties()定義多個(gè)對(duì)象屬性標(biāo)簽
Object.defineProperties(person, {
title: {
value: 'fe',
enumerable: true,
},
corp: {
value: 'SDF',
enumerable: true,
},
salary: {
value: '50000',
enumerable: true,
writable: true
}
});
console.log(person);
console.log(Object.getOwnPropertyDescriptor(person, 'corp'));
console.log(Object.getOwnPropertyDescriptor(person, 'salary'));
Object.defineProperties()
這個(gè)函數(shù)接收兩個(gè)參數(shù),第一個(gè)參數(shù)是你要定義屬性的對(duì)象,第二個(gè)參數(shù)是一個(gè)對(duì)象抄肖,對(duì)象里包含屬性值列表集久信。
例子
var person = {};
Object.defineProperties(person, {
title: {
value: 'fe',
enumerable: true,
},
corp: {
value: 'SDF',
enumerable: true,
},
salary: {
value: '50000',
enumerable: true,
writable: true
},
luck: {
get: function() {
return Math.random() > 0.5 ? 'good' : 'bad';
}
},
promote: {
set: function(level) {
this.salary *= 1 + level * 0.1;
}
}
});
console.log(Object.getOwnPropertyDescriptor(person, 'salary'));
console.log(Object.getOwnPropertyDescriptor(person, 'corp'));
console.log(person.salary);
person.promote = 3;
console.log(person.salary);
console.log(person.luck);
JavaScropt對(duì)象標(biāo)簽、對(duì)象序列化
對(duì)象標(biāo)簽
對(duì)象級(jí)別也是有標(biāo)簽的漓摩,主要有三種
[[proto]]
[[class]]
[[extensible]]
原型標(biāo)簽
__proto__
__proto__
實(shí)際上就是原型裙士,比如說(shuō)當(dāng)我們用new
構(gòu)造器的方式去實(shí)例化函數(shù)對(duì)象,那么這個(gè)實(shí)例化對(duì)象的原型鏈會(huì)指向構(gòu)造器的prototype
管毙,一般的對(duì)象也會(huì)有原型腿椎,指向 Object.prototype
然后在往上就是nall
。
class標(biāo)簽
var toString = Object.prototype.toString;
function getType(o) {
return toString.call(o).slice(8, -1);
};
console.log(toString.call(null)); //[object Null]
console.log(getType(null)); //Null
console.log(getType(undefined)); //Undefined
console.log(getType(1)); //Number
console.log(getType(new Number(1))); //Number
console.log(typeof new Number(1)); //object
console.log(getType(true)); //Boolean
console.log(getType(new Boolean(true))); //Boolean
class標(biāo)簽是沒(méi)有一個(gè)直接的方式去查看他或者是修改他夭咬,可以間接的通過(guò)Object.prototype.toString;
的方式來(lái)去獲取class啃炸,
var toString = Object.prototype.toString;
先把Object.prototype.toString;
這樣一個(gè)函數(shù)拿到,賦值給toString
這樣方便后面代碼簡(jiǎn)短一些卓舵,
function getType(o) {
return toString.call(o).slice(8, -1);
};
定義一個(gè)方法南用,返回toString.call(o)
來(lái)調(diào)用這個(gè)函數(shù)方法,并且把參數(shù)o
作為this
傳進(jìn)去掏湾,然后用slice(8, -1);
表示是截取從第八個(gè)字符開(kāi)始裹虫,一直到最后。
調(diào)用getType(1); //Number
getType(1)方法會(huì)返回類型融击。
extensible標(biāo)簽
extensible標(biāo)簽表示你這個(gè)對(duì)象是否可擴(kuò)展筑公,言外之意就是說(shuō)對(duì)象上的屬性是否可以被繼續(xù)添加。
var obj={x:1,y:2};//創(chuàng)建對(duì)象
Object.isExtensible(obj);//true
創(chuàng)建對(duì)象obj砚嘴,通過(guò)Object.isExtensible(obj);
來(lái)判斷對(duì)象是否可擴(kuò)展十酣,一般情況下默認(rèn)返回true涩拙。表示可以擴(kuò)展际长。
那么怎么樣不讓他擴(kuò)展,不可修改不可刪除凍結(jié)對(duì)象
var obj={x:1,y:2};//創(chuàng)建對(duì)象
Object.isExtensible(obj);//true obj對(duì)象可擴(kuò)展
Object.preventExtensions(obj); //設(shè)置obj對(duì)象不可擴(kuò)展
Object.isExtensible(obj);//false obj對(duì)象不可擴(kuò)展
obj.d=2; //嘗試給obj添加新的屬性會(huì)發(fā)現(xiàn)添加失敗
console.log(obj.d);//undefined
//如果已經(jīng)組織對(duì)象可擴(kuò)展兴泥,那么對(duì)象上的屬性標(biāo)簽是否會(huì)發(fā)生變化呢工育?
console.log(Object.getOwnPropertyDescriptor(obj, 'x'));
//value: 1, writable: true, enumerable: true, configurable: true
//雖然我們阻止了對(duì)象不可添加新屬性,但是已有熟悉仍然可以修改和刪除搓彻,也是可以枚舉的如绸。
//可以通過(guò)
Object.seal(obj);//會(huì)把對(duì)象上的屬性的configurable設(shè)置為false不可刪除
console.log(Object.getOwnPropertyDescriptor(obj, 'x'));
//value: 1, writable: true, enumerable: true, configurable: false
console.log(Object.isSealed(obj));//true 判斷對(duì)象是否被隱藏不可刪除
Object.freeze(obj);//讓對(duì)象凍結(jié)不可寫(xiě)
console.log(Object.getOwnPropertyDescriptor(obj, 'x'));
//value: 1, writable: false, enumerable: true, configurable: false
console.log(Object.isFrozen(obj));//true 判斷對(duì)象是否被不可寫(xiě)
序列化
var obj = {
x: 1,
y: true,
z: [1, 2, 3],
nullval: null
};
console.log(obj);
console.log(JSON.stringify(obj)); //{"x":1,"y":true,"z":[1,2,3],"nullval":null}
var obj1 = {
val: undefined,
a: NaN,
b: Infinity,
c: Date()
};
console.log(obj1);
console.log(JSON.stringify(obj1)); //{"a":null,"b":null,"c":"Fri Dec 16 2016 22:25:04 GMT+0800 (中國(guó)標(biāo)準(zhǔn)時(shí)間)"}
var obj2 = JSON.parse('{"x":1}');
console.log(obj2); //Object {x: 1}
console.log(obj2.x); //1
定義obj 字面量對(duì)象,有一些屬性旭贬,通過(guò)JSON.stringify(obj));
方法返回一個(gè)字符串{"x":1,"y":true,"z":[1,2,3],"nullval":null}
返回的字符串就是這個(gè)對(duì)象的序列化的結(jié)果怔接。
需要注意一點(diǎn)這個(gè)序列化是有一些坑的,如果你的屬性值是undefined
的話稀轨,那么就不會(huì)出現(xiàn)在序列化的結(jié)果當(dāng)中扼脐。
如果后端返回一個(gè)JSON數(shù)據(jù)我們?cè)趺窗阉D(zhuǎn)換成js對(duì)象呢?
使用JSON.parse('{"x":1}');
方法,需要注意的是合法的json屬性必須以雙引號(hào)引起來(lái)瓦侮。
序列化-自定義
var obj = {
x: 1,
y: 2,
o: {
o1: 1,
o2: 2,
toJSON: function() {
return this.o1 + this.o2;
}
}
};
console.log(JSON.stringify(obj)); //{"x":1,"y":2,"o":3}
obj對(duì)象下有個(gè)屬性o他的值是一個(gè)對(duì)象艰赞,那么這個(gè)對(duì)象序列化的結(jié)果我可能想要自定義,那么我們只需要在這個(gè)當(dāng)前的層級(jí)下寫(xiě)一個(gè)toJSON
他的值是一個(gè)函數(shù)肚吏,toJSON
是固定這個(gè)key一定要這樣寫(xiě)方妖,然后這個(gè)函數(shù)會(huì)返回return this.o1 + this.o2;
這個(gè)this會(huì)指向當(dāng)前層級(jí)的數(shù)也就是o,
這時(shí)候去JSON.stringify(obj));
的時(shí)候罚攀,這里面的o通過(guò)toJSON
這樣一個(gè)方法來(lái)去返回的党觅。
其他對(duì)象方法
var obj = { //定義對(duì)象obj
x: 1,
y: 2
};
obj.toString(); //"[object Object]" 調(diào)用對(duì)象的toString方法會(huì)返回"[object Object]"這樣的字符串實(shí)際上沒(méi)有太大意義
//定義自己對(duì)象上個(gè)的toString方法
obj.toString = function() {
return this.x + this.y; //返回對(duì)象的x和y相加作為結(jié)果
}
"Result" + obj; //"Result3" 左邊是字符串這樣會(huì)理解為字符串拼接那么他就會(huì)調(diào)用obj.toString所以返回結(jié)果"Result3"
+ obj; //3 用一員加號(hào)操作符是可以把對(duì)象嘗試轉(zhuǎn)換為數(shù)字的,如果定義了obj.toString也會(huì)去調(diào)用obj.toString返回3
//valueOf是嘗試把對(duì)象轉(zhuǎn)換為基本類型的時(shí)候會(huì)自動(dòng)去調(diào)用的一個(gè)函數(shù)坞生,這里自定義返回值
obj.valueOf = function() {
return this.x + this.y + 100;
} + obj; //103 再去用一員加號(hào)操作符把他轉(zhuǎn)換為數(shù)字這次返回的結(jié)果是103是從這個(gè)valueOf而來(lái)的
"Result" + obj; //"Result103"
需要主要的是這里面valueOf和toString都存在的時(shí)候那么不管是一元的加號(hào)還是2元的字符串拼接在做具體操作時(shí)仔役,都會(huì)嘗試把對(duì)象轉(zhuǎn)換為基本類型,那么他會(huì)先去找valueOf是己。如果valueOf返回的是基本類型那么就以valueOf的值作為結(jié)果反之如果valueOf不存在或者返回的是對(duì)象又兵,那么就會(huì)去找toString。如果valueOf和toString都沒(méi)有或者都返回的對(duì)象卒废,那么就會(huì)報(bào)錯(cuò)沛厨。