中文字幕日韩精品一区二区免费_精品一区二区三区国产精品无卡在_国精品无码专区一区二区三区_国产αv三级中文在线

JavaScript精粹基礎(chǔ)進(jìn)階(4)對(duì)象

轉(zhuǎn)載請(qǐng)注明出處

網(wǎng)站建設(shè)哪家好,找創(chuàng)新互聯(lián)!專注于網(wǎng)頁(yè)設(shè)計(jì)、網(wǎng)站建設(shè)、微信開發(fā)、微信小程序開發(fā)、集團(tuán)企業(yè)網(wǎng)站建設(shè)等服務(wù)項(xiàng)目。為回饋新老客戶創(chuàng)新互聯(lián)還提供了敘永免費(fèi)建站歡迎大家使用!

原文連接http://blog.huanghanlian.com/article/5b698ed6b8ea642ea9213f4c

對(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ù)類型

JavaScript 精粹 基礎(chǔ) 進(jìn)階(4)對(duì)象

函數(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);

JavaScript 精粹 基礎(chǔ) 進(jìn)階(4)對(duì)象

創(chuàng)建一個(gè)函數(shù)聲明
每一個(gè)函數(shù)都會(huì)有一個(gè)foo.prototype對(duì)象屬性

function foo(){};
foo.prototype.z=1;
console.log(foo.prototype);

JavaScript 精粹 基礎(chǔ) 進(jìn)階(4)對(duì)象

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);

JavaScript 精粹 基礎(chǔ) 進(jìn)階(4)對(duì)象

通過(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。

JavaScript 精粹 基礎(chǔ) 進(jìn)階(4)對(duì)象

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 精粹 基礎(chǔ) 進(jìn)階(4)對(duì)象

JavaScript 屬性操作

讀寫對(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,有xy兩個(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),并且他的順序是不確定的。

屬性讀寫-異常

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
}

這樣寫出來(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ì)getset方法,來(lái)去訪問(wèn)屬性age

語(yǔ)法

getset關(guān)鍵字開頭,空格,然后是屬性的名字,然后是括號(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

JavaScript 精粹 基礎(chǔ) 進(jìn)階(4)對(duì)象

Object.defineProperty(foo.prototype, 'z', {
    get: function() {
        return 1;
    }
});

通過(guò)definePropertygit方法來(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)有getset方法的時(shí)候,那么當(dāng)我們嘗試去賦值的時(shí)候,實(shí)際上會(huì)走原型上getset方法的,而不會(huì)再去通過(guò)給當(dāng)前對(duì)象obj添加新屬性。

Object.defineProperty(obj, 'z', {
    value: 100,
    configurable: true
});

通過(guò)Object.definePropertyobj目標(biāo)對(duì)象去添加一個(gè)屬性z

  • value:屬性的值給屬性賦值
  • writable:如果為false,屬性的值就不能被重寫。
  • 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ù)去向上查找zget方法。

小案例

var o={z:2};
Object.defineProperty(o,'x',{value:1});//默認(rèn)writable=false只讀,configurable=false不可寫
o.z=6;
o.x=6;
console.log(o);

JavaScript 精粹 基礎(chǔ) 進(jìn)階(4)對(duì)象

案例解釋

var o={};
Object.defineProperty(o,'x',{value:1});//默認(rèn)writable=false只讀,configurable=false不可寫
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,這樣就可以覆蓋掉原型鏈上的不可寫的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,屬性的值就不能被重寫。
  • 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,//屬性的值就不能被重寫。
    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));

JavaScript 精粹 基礎(chǔ) 進(jìn)階(4)對(duì)象

新創(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'));

JavaScript 精粹 基礎(chǔ) 進(jìn)階(4)對(duì)象

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);

JavaScript 精粹 基礎(chǔ) 進(jìn)階(4)對(duì)象

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

對(duì)象標(biāo)簽

對(duì)象級(jí)別也是有標(biāo)簽的,主要有三種

  1. [[proto]]

  2. [[class]]

  3. [[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è)字符開始,一直到最后。

調(diào)用getType(1); //NumbergetType(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é)不可寫
console.log(Object.getOwnPropertyDescriptor(obj, 'x'));
//value: 1, writable: false, enumerable: true, configurable: false
console.log(Object.isFrozen(obj));//true   判斷對(duì)象是否被不可寫

序列化

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í)下寫一個(gè)toJSON他的值是一個(gè)函數(shù),toJSON是固定這個(gè)key一定要這樣寫,然后這個(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ò)。

網(wǎng)站標(biāo)題:JavaScript精粹基礎(chǔ)進(jìn)階(4)對(duì)象
網(wǎng)站路徑:http://m.rwnh.cn/article10/jcjigo.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供、網(wǎng)站導(dǎo)航外貿(mào)網(wǎng)站建設(shè)、品牌網(wǎng)站建設(shè)、企業(yè)網(wǎng)站制作、云服務(wù)器

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

宁化县| 延津县| 吉木乃县| 达孜县| 松原市| 福贡县| 前郭尔| 武川县| 浙江省| 卢龙县| 绥化市| 仁寿县| 武穴市| 鄢陵县| 射阳县| 安多县| 汉川市| 奇台县| 法库县| 巴里| 吉木萨尔县| 交城县| 水富县| 长海县| 兰西县| 通辽市| 安乡县| 庐江县| 温泉县| 商丘市| 凯里市| 青铜峡市| 大冶市| 巴塘县| 冕宁县| 大名县| 长治市| 伊春市| 陇西县| 天祝| 靖宇县|