JavaScript精粹基礎進階(4)對象

轉載請注明出處

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

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

對象中包含一系列屬性,這些屬性是無序的。每個屬性都有一個字符串key和對應的value。

JavaScript 對象概述

概述

對象中包含一系列屬性,這些屬性是無序的。每個屬性都有一個字符串key和對應的value。

var obj = {x : 1, y : 2};    //定義obj對象, 有兩個屬性x和y
obj.x; // 1   //訪問對應obj.x屬性取到對應的值
obj.y; // 2   //訪問對應obj.y屬性取到對應的值

這里有兩個重點,一個是屬性是無序的,再一個每一個key是字符串。

探索對象的key

var obj = {};    //定義對象obj
obj[1] = 1;      //動態(tài)賦值數字1屬性值為1
obj['1'] = 2;    //動態(tài)賦值字符串1屬性值為2
console.log(obj); // Object {1: 2}  //實際上結果指向的是同一個屬性

//每個屬性都有一個字符串key和對應的value。

obj[{}] = true;    //[{}] 空對象作為key
obj[{x : 1}] = true;     //對象帶有屬性的對象作為key  //js都會把它轉換成字符串然后再去處理,最終指向的是同一個屬性
console.log(obj)// Object {1: 2, [object Object]: true}

回顧-數據類型

JavaScript 精粹 基礎 進階(4)對象

函數,數組,日期,正則等都是對象

對象結構

var obj = {};    //字面量空對象
obj.y = 2;       //賦值創(chuàng)建屬性x
obj.x = 1;       //賦值創(chuàng)建屬性y

對象有個特點,他的屬性可以動態(tài)的添加或刪除的

函數對象

function foo(){};
console.log(foo.prototype);

JavaScript 精粹 基礎 進階(4)對象

創(chuàng)建一個函數聲明
每一個函數都會有一個foo.prototype對象屬性

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

JavaScript 精粹 基礎 進階(4)對象

foo.prototype對象屬性添加屬性z賦值為1,foo.prototype對象屬性下有個constructor屬性方法,該屬性其實是指向自己本身。

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

var obj =new foo();
console.log(obj);

JavaScript 精粹 基礎 進階(4)對象

通過new去實例化foo()函數var obj =new foo();那么這個obj原型就會指向構造器的prototype屬性也就是foo.prototype,可以通過上圖看出打印輸出是一樣的。

JavaScript 創(chuàng)建對象,原型鏈

對象創(chuàng)建-字面量

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

對象字面量 ,用{}設置屬性

var obj2 = {
x : 1,
y : 2,
o : {
z : 3,
n : 4
}
};

對象字面量也可以做一些嵌套,比如某些屬性值可以又是對象

創(chuàng)建對象-new/原型鏈

還有一種就是使用new構造器的方法創(chuàng)建對象,先來了解javascript中的原型鏈。

什么是原型鏈

function foo(){}    //定義函數對象  
foo.prototype.z = 3;      //函數對象默認帶foo.prototype對象屬性  對象添加z屬性=3

var obj =new foo();    //用構造器方式構造新的對象
obj.y = 2;    //通過賦值添加2個屬性給obj
obj.x = 1;   //通過new去構造這樣一個對象他的主要特點是,他的原型會指向構造器的foo.prototype屬性

obj.x; // 1  //訪問obj.x發(fā)現(xiàn)對象上有x返回1
obj.y; // 2  //訪問obj.y發(fā)現(xiàn)對象上有x返回2
obj.z; // 3  //obj上沒有z并不會停止查找,會去查找他的原型foo.prototype.z返回3
typeof obj.toString; // ‘function'  這是一個函數,toString是Object.prototype上面的每個對象都有
'z' in obj; // true     obj.z是從foo.prototype繼承而來的,所以說obj里面有z
obj.hasOwnProperty('z'); // false   表示z并不是obj直接對象上的,而是對象原型鏈上的。

但是如果是賦值的話結果就一樣了。

比如我們賦值obj.z=5

如果給obj.z嘗試去賦值,就不會像原型鏈上去查找了。先看obj.z有沒有,有的話修改它的值,沒有的話,在對象上添加obj.z。

JavaScript 精粹 基礎 進階(4)對象

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  刪除對象上的z屬性
obj.z; // 3  //這樣就能獲取原型鏈上的z

對象創(chuàng)建-Object.create

從字面量理解是對象創(chuàng)建

Object.create({x:1});是系統(tǒng)內置的函數,這個函數會接收一個參數,一般是一個對象。他會返回一個新創(chuàng)建的對象,并且讓這個對象的原型指向參數,參數一般是個對象。

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 精粹 基礎 進階(4)對象

JavaScript 屬性操作

讀寫對象屬性

var obj = {
    x: 1,
    y: 2
};
console.log(obj.x); // 1
console.log(obj["y"]); // 2

obj["x"] = 3;
obj.y = 4;

創(chuàng)建對象字面量obj,有xy兩個屬性,可以用obj.y(點)操作符去訪問他的屬性,也可以用obj["y"][中括號這里需要是字符串]

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']可以在[]內拼接字符串,obj.x+""不是那么方便

var obj = {
    x1: 1,
    x2: 2
};
var p;
for (p in obj) {
    console.log(obj[p]);
}

用for...in遍歷所有屬性
需要注意的是用for...in去遍歷的話,有可能把原型鏈上的屬性也遍歷出來,并且他的順序是不確定的。

屬性讀寫-異常

var obj = {
    x: 1
};//創(chuàng)建對象obj
console.log(obj.y); //如果訪問一個不存在的屬性會進行原型鏈查找如果找到末端還是找不到就會返回 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;
}//判斷當obj.y存在把他取出來

//巧用運算符
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,  不允許刪除

//通過getOwnPropertyDescriptor方法去獲取一個屬性中所有的標簽,第一個參數是你要查看的對象,第二個是你要去檢測的屬性這樣就能拿到屬性的描述器
var descriptor = Object.getOwnPropertyDescriptor(Object, 'prototype');
console.log(descriptor);

屬性檢測

var cat = new Object;  //使用new 構造對象
cat.legs = 4;    //賦值屬性legs值為4
cat.name = "Kitty";  //賦值屬性name值為Kitty

'legs' in cat; // true   表示cat中有l(wèi)egs屬性 in操作符是會向原型鏈上查找的
'abc' in cat; // false   表示cat中沒有abc屬性
"toString" in cat; // true, 繼承 property有toString屬性

cat.hasOwnProperty('legs'); // true   表示cat直接量屬性有l(wèi)egs
cat.hasOwnProperty('toString'); // false   表示cat直接量屬性沒有toString   toString是在原型有

cat.propertyIsEnumerable('legs'); // true  legs可枚舉  查看是否可枚舉propertyIsEnumerable   for...in會被循環(huán)
cat.propertyIsEnumerable('toString'); // false   toString不可枚舉  查看是否可枚舉propertyIsEnumerable   for...in不會被循環(huán)

自定義對象屬性,讓他的枚舉標簽是false

var cat = new Object;  //使用new 構造對象
cat.legs = 4;    //賦值屬性legs值為4
cat.name = "Kitty";  //賦值屬性name值為Kitty

'legs' in cat; // true   表示cat中有l(wèi)egs屬性 in操作符是會向原型鏈上查找的
'abc' in cat; // false   表示cat中沒有abc屬性
"toString" in cat; // true, 繼承 property有toString屬性

cat.hasOwnProperty('legs'); // true   表示cat直接量屬性有l(wèi)egs
cat.hasOwnProperty('toString'); // false   表示cat直接量屬性沒有toString   toString是在原型有

cat.propertyIsEnumerable('legs'); // true  legs可枚舉  查看是否可枚舉propertyIsEnumerable   for...in會被循環(huán)
cat.propertyIsEnumerable('toString'); // false   toString不可枚舉  查看是否可枚舉propertyIsEnumerable   for...in不會被循環(huán)

//通過Object.defineProperty給cat目標對象去添加一個屬性price
//enumerable:是否能在for...in循環(huán)中遍歷出來或在Object.keys中列舉出來。
//value:屬性的值給屬性賦值
Object.defineProperty(cat, 'price', {enumerable: false, value: 1000});
cat.propertyIsEnumerable('price'); // false  price不可枚舉  查看是否可枚舉propertyIsEnumerable   for...in不會被循環(huán)
cat.hasOwnProperty('price'); // true   表示cat直接量屬性有price
console.log(cat)
for(var k in cat){
    console.log(cat[k]);//循環(huán)出來看看能不能被枚舉
}

判斷對象屬性是否存在進行操作

if (cat && cat.legs) {
    cat.legs *= 2;
}//8

判斷cat是否存在且cat.legs不是undefined的時候,讓cat.legs值乘等于2,表示cat.legs乘以2再賦值給cat.legs

if (cat.legs !== undefined) {
    // only if cat.legs is not undefined
}

判斷cat.legs不等于undefined的時候去做動作

if (cat.legs !== undefined) {
    // only if cat.legs is not undefined
}

判斷cat.legs嚴格不等于undefined的時候去做動作

屬性枚舉

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
}

這樣寫出來的對象原型鏈屬性默認是不可枚舉的,所以for....in的時候原型鏈不會出來。

var o = {
    x: 1,
    y: 2,
    z: 3
};
var obj = Object.create(o);  //創(chuàng)建obj對象以o對象作為原型
obj.a = 4;

console.log(obj)
var key;
for (key in obj) {
    console.log(key); // a, x, y, z
}

創(chuàng)建obj對象以o對象作為原型
所有對象上的屬性,和原型上的屬性都會遍歷中顯示出來

那有時候我只想處理對象上的屬性,不想遍歷我對象原型鏈上的屬性。

我們需要在加一個obj.hasOwnProperty(key)的判斷,來過濾掉原型鏈上的屬性就可以了。

var o = {
    x: 1,
    y: 2,
    z: 3
};
var obj = Object.create(o);  //創(chuàng)建obj對象以o對象作為原型
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('年齡不能設置' + val);
    }
}
console.log(man.age); //23
man.age = 100; //年齡不能設置100
console.log(man.age); //23

定義了一個對象man有屬性name值是huang,這里定義了一對getset方法,來去訪問屬性age

語法

getset關鍵字開頭,空格,然后是屬性的名字,然后是括號再方括號,里面是一個函數體,

get方法會返回當前日期的年份減去我的出生日,會拿到我的年齡。

set方法會拿到括號賦值的值,唯一的參數創(chuàng)進來。

當訪問console.log(man.age); //23會返回get方法,

當使用man.age = 100;也就是說給set去賦值的時候,就會去調用set方法,就會輸出年齡不能設置100

再去輸出console.log(man.age); //23會發(fā)現(xiàn)仍然是23,因為set沒做任何的事情。

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)建一個foo函數,就會有一個foo.prototype

JavaScript 精粹 基礎 進階(4)對象

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

通過definePropertygit方法來創(chuàng)建z屬性,git方法只是固定的返回1。

var obj = new foo();

使用new方式來創(chuàng)建一個新的對象obj,這樣這個obj對象的原型會指向foo.prototype

console.log(obj.z); //1

當我們去訪問obj.z的時候obj對象上沒有z直接量屬性,所以他會向上去查找,foo.prototype原型,發(fā)現(xiàn)有一個z屬性用的是get方法,這樣就能返回1,

obj.z = 10;
console.log(obj.z); //還是輸出1

那么我賦值,嘗試給z賦值為10,如果z不是用get方式賦值的是通過foo.prototype.z原型賦值的話,再使用直接量去賦值是可以成功的,值會返回到obj這個對象上,但是在這里賦值并沒有成功。仍然返回1。

這是因為當obj對象上沒有z直接量屬性的時候,并且他的原型鏈查找發(fā)現(xiàn)有getset方法的時候,那么當我們嘗試去賦值的時候,實際上會走原型上getset方法的,而不會再去通過給當前對象obj添加新屬性。

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

通過Object.definePropertyobj目標對象去添加一個屬性z

  • value:屬性的值給屬性賦值
  • writable:如果為false,屬性的值就不能被重寫。
  • get: 一旦目標屬性被訪問就會調回此方法,并將此方法的運算結果返回用戶。
  • set:一旦目標屬性被賦值,就會調回此方法。
  • configurable:如果為false,則任何嘗試刪除目標屬性或修改屬性以下特性(writable, configurable, enumerable)的行為將被無效化。
  • enumerable:是否能在for...in循環(huán)中遍歷出來或在Object.keys中列舉出來。
console.log(obj.z);//100

這個時候obj.z是obj的直接量返回100

delete obj.z;

由于configurable: true所以刪除是成功的

console.log(obj.z);//1

這里因為直接量z被刪除們說以他會繼續(xù)去向上查找zget方法。

小案例

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

JavaScript 精粹 基礎 進階(4)對象

案例解釋

var o={};
Object.defineProperty(o,'x',{value:1});//默認writable=false只讀,configurable=false不可寫
var obj=Object.create(o);//創(chuàng)建obj對象以o對象作為原型
console.log(obj.x);//1   會向上查找返回原型鏈x屬性值1
obj.x=200; //嘗試去賦值200
console.log(obj.x);//賦值后打印任然是1

//那么如何去在obj對象添加x屬性呢?

//還是要用Object.defineProperty

//給obj對象添加一個自己的屬性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屬性標簽

屬性標簽

怎樣去看某一個對象上的屬性上都有哪些標簽

console.log(Object.getOwnPropertyDescriptor({pro:true}, 'pro'));檢查一個字面量的對象,添加屬性`pro:true`看字面量下的屬性`pro`的屬性標簽
//configurable:true,enumerable:true,value:true,writable:true
console.log(Object.getOwnPropertyDescriptor({pro:true}, 'a'));//去查一個根本不存在的屬性返回undefined
//undefined

通過Object.getOwnPropertyDescriptor(參數1,"參數2")方法可以返回一個對象,這個對象上會顯示 當前這個屬性下所有的標簽,這個函數會接收兩個參數,第一個是你要去判斷的對象,第二個是一個字符串的屬性名,

  • value:屬性的值給屬性賦值
  • writable:如果為false,屬性的值就不能被重寫。
  • get: 一旦目標屬性被訪問就會調回此方法,并將此方法的運算結果返回用戶。
  • set:一旦目標屬性被賦值,就會調回此方法。
  • configurable:如果為false,則任何嘗試刪除目標屬性或修改屬性以下特性(writable, configurable, enumerable)的行為將被無效化。
  • enumerable:是否能在for...in循環(huán)中遍歷出來或在Object.keys中列舉出來
    console.log(Object.getOwnPropertyDescriptor({pro:true}, 'pro'));檢查一個字面量的對象,添加屬性`pro:true`看字面量下的屬性`pro`的屬性標簽

得到的結果是

//configurable:true,enumerable:true,value:true,writable:true

那么怎么去設置或者說設置對象的屬性標簽呢?

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)建一個空對象

var person = {};

通過Object.defineProperty(參數1,"參數2",{參數1})第一個參數是要添加屬性的對象,第二個參數是一個字符串屬性的名字,第三個參數是一個對象,這個對象里面就是具體每一個標簽的值,

Object.defineProperty(person, 'name', {
    configurable: false,//不可刪除
    writable: false,//屬性的值就不能被重寫。
    enumerable: true,//可枚舉
    value: "繼小鵬"http://屬性的值給屬性賦值
});

結果符合預期

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 精粹 基礎 進階(4)對象

新創(chuàng)建的屬性enumerable: false,不可枚舉,可以通過Object.keys(person)的方法來去獲取對象上所有的key
因為新創(chuàng)建的屬性enumerable: false,不可枚舉所有不可見。

使用Object.defineProperties()定義多個對象屬性標簽

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 精粹 基礎 進階(4)對象

Object.defineProperties()這個函數接收兩個參數,第一個參數是你要定義屬性的對象,第二個參數是一個對象,對象里包含屬性值列表集。

例子

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 精粹 基礎 進階(4)對象

JavaScropt對象標簽、對象序列化

對象標簽

對象級別也是有標簽的,主要有三種

  1. [[proto]]

  2. [[class]]

  3. [[extensible]]

原型標簽__proto__

__proto__實際上就是原型,比如說當我們用new構造器的方式去實例化函數對象,那么這個實例化對象的原型鏈會指向構造器的prototype,一般的對象也會有原型,指向 Object.prototype然后在往上就是nall

class標簽

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標簽是沒有一個直接的方式去查看他或者是修改他,可以間接的通過Object.prototype.toString;的方式來去獲取class,

var toString = Object.prototype.toString;

先把Object.prototype.toString;這樣一個函數拿到,賦值給toString這樣方便后面代碼簡短一些,

function getType(o) {
    return toString.call(o).slice(8, -1);
};

定義一個方法,返回toString.call(o) 來調用這個函數方法,并且把參數o作為this傳進去,然后用slice(8, -1);表示是截取從第八個字符開始,一直到最后。

調用getType(1); //NumbergetType(1)方法會返回類型。

extensible標簽

extensible標簽表示你這個對象是否可擴展,言外之意就是說對象上的屬性是否可以被繼續(xù)添加。

var obj={x:1,y:2};//創(chuàng)建對象
Object.isExtensible(obj);//true

創(chuàng)建對象obj,通過Object.isExtensible(obj);來判斷對象是否可擴展,一般情況下默認返回true。表示可以擴展。

那么怎么樣不讓他擴展,不可修改不可刪除凍結對象

var obj={x:1,y:2};//創(chuàng)建對象
Object.isExtensible(obj);//true   obj對象可擴展

Object.preventExtensions(obj);    //設置obj對象不可擴展
Object.isExtensible(obj);//false   obj對象不可擴展
obj.d=2;   //嘗試給obj添加新的屬性會發(fā)現(xiàn)添加失敗
console.log(obj.d);//undefined

//如果已經組織對象可擴展,那么對象上的屬性標簽是否會發(fā)生變化呢?

console.log(Object.getOwnPropertyDescriptor(obj, 'x'));
//value: 1, writable: true, enumerable: true, configurable: true
//雖然我們阻止了對象不可添加新屬性,但是已有熟悉仍然可以修改和刪除,也是可以枚舉的。

//可以通過
Object.seal(obj);//會把對象上的屬性的configurable設置為false不可刪除
console.log(Object.getOwnPropertyDescriptor(obj, 'x'));
//value: 1, writable: true, enumerable: true, configurable: false
console.log(Object.isSealed(obj));//true   判斷對象是否被隱藏不可刪除

Object.freeze(obj);//讓對象凍結不可寫
console.log(Object.getOwnPropertyDescriptor(obj, 'x'));
//value: 1, writable: false, enumerable: true, configurable: false
console.log(Object.isFrozen(obj));//true   判斷對象是否被不可寫

序列化

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 (中國標準時間)"}

var obj2 = JSON.parse('{"x":1}');
console.log(obj2); //Object {x: 1}
console.log(obj2.x); //1

定義obj 字面量對象,有一些屬性,通過JSON.stringify(obj));方法返回一個字符串{"x":1,"y":true,"z":[1,2,3],"nullval":null}返回的字符串就是這個對象的序列化的結果。

需要注意一點這個序列化是有一些坑的,如果你的屬性值是undefined的話,那么就不會出現(xiàn)在序列化的結果當中。

如果后端返回一個JSON數據我們怎么把他轉換成js對象呢?

使用JSON.parse('{"x":1}');方法,需要注意的是合法的json屬性必須以雙引號引起來。

序列化-自定義

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對象下有個屬性o他的值是一個對象,那么這個對象序列化的結果我可能想要自定義,那么我們只需要在這個當前的層級下寫一個toJSON他的值是一個函數,toJSON是固定這個key一定要這樣寫,然后這個函數會返回return this.o1 + this.o2;這個this會指向當前層級的數也就是o,

這時候去JSON.stringify(obj));的時候,這里面的o通過toJSON這樣一個方法來去返回的。

其他對象方法

var obj = {   //定義對象obj
x: 1,
y: 2
};
obj.toString(); //"[object Object]"   調用對象的toString方法會返回"[object Object]"這樣的字符串實際上沒有太大意義

//定義自己對象上個的toString方法
obj.toString = function() {
return this.x + this.y; //返回對象的x和y相加作為結果
}

"Result" + obj; //"Result3" 左邊是字符串這樣會理解為字符串拼接那么他就會調用obj.toString所以返回結果"Result3"

  • obj; //3 用一員加號操作符是可以把對象嘗試轉換為數字的,如果定義了obj.toString也會去調用obj.toString返回3

//valueOf是嘗試把對象轉換為基本類型的時候會自動去調用的一個函數,這里自定義返回值
obj.valueOf = function() {
return this.x + this.y + 100;
} + obj; //103 再去用一員加號操作符把他轉換為數字這次返回的結果是103是從這個valueOf而來的
"Result" + obj; //"Result103"



需要主要的是這里面valueOf和toString都存在的時候那么不管是一元的加號還是2元的字符串拼接在做具體操作時,都會嘗試把對象轉換為基本類型,那么他會先去找valueOf。如果valueOf返回的是基本類型那么就以valueOf的值作為結果反之如果valueOf不存在或者返回的是對象,那么就會去找toString。如果valueOf和toString都沒有或者都返回的對象,那么就會報錯。

網站標題:JavaScript精粹基礎進階(4)對象
網站路徑:http://muchs.cn/article10/jcjigo.html

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

廣告

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

成都網站建設