淺顯易懂----javascript對象全解析(一)

前言javascript


我先先看一下javascript權威指南中對 object的定義:java

對象是一種複合值:他將不少值(原始值或者其餘對象)聚合在一塊兒,能夠經過名字訪問這些值。對象也能夠看作是屬性的無序集合,每一個屬性都是一個鍵/值對(key/value)。 咱們看到的大多數引用類型值都是 Object 類型的實例;並且,Object 也是 ECMAScript 中使用最多的一個類型。對象其實就是一組數據和功能的集合。json

JavaScript 中一共有六種主要類型:數組

• string
• number
• boolean
• null
• undefined
• object
複製代碼

其中基本數據類型有五種:UndefinedNullBooleanNumberString。還有 一種複雜數據類型,也就是對象-----Object函數

null其實表示一個空對象的指針。這也是使用 typeof 操做符檢測 null 值時會返回"object"的緣由 ui

console.log(typeof null);   //object
複製代碼

實際上,JavaScript 中還有許多特殊的對象子類型,能夠稱之爲複雜基本類型。this

內置對象

此外,JavaScript 中還有一些對象子類型,一般被稱爲內置對象。有些內置對象的名字看起來和簡單基礎類型同樣,不過實際上它們的關係更復雜:spa

• String
 • Number
 • Boolean
 • Object
 • Function
 • Array
 • Date 
 • RegExp 
 • Error
複製代碼

內置對象將在下篇文章繼續討論。prototype

建立對象

1.1 對象字面量表示法

建立一個名爲person的對象:設計

let person = { 
    name : "小黃瓜", 
    age : 22 
};
複製代碼

在使用對象字面量語法時,屬性名也可使用字符串:

let person = { 
    "name" : "小黃瓜", 
    "age" : 22, 
};
複製代碼

這裏的數值屬性名會自動轉換爲字符串。

使用對象字面量語法時,若是留空花括號,則能夠定義只包含默認屬性和方法的對象:

let person = {};    ////與 new Object()相同
person.name = "小黃瓜";
person.age = 22;
複製代碼

1.2 使用new操做符建立對象

new操做符建立並初始化一個新對象,操做符new後面跟一個構造函數Object

let person = new Object(); 
person.name = "小黃瓜"; 
person.age = 22;
複製代碼

1.3 Object.create()方法

let person = Object.create({name : '小黃瓜'});
person.name   //小黃瓜
複製代碼

Object.create()其實是建立了一個空對象,並將原型指針指向了傳入的第一個參數。

Object.create = function(new){
    let NewObject = {};
    NewObject.prototype = new;
    return new NewObject();
}
複製代碼

屬性的查詢和設置

2.1 經過 . 的方式

let person = {
    name : '小黃瓜',
    age : 22
}
//查詢值
console.log(person.name);   //小黃瓜
//設置值
person.name = 'guanguan';
console.log(person.name);    //guanguan
複製代碼

2.2 經過 [] 表示法

let person = {
    name : 'xiaohuanggua',
    age : 22
}
//查詢值
console.log(person["name"]);  //xiaohuanggua
//設置值
person["name"] = 'guanguan';
console.log(person["name"]);  //guanguan

//但方括號語法的主要優勢是能夠經過變量來訪問屬性
let newName = "name";
console.log(person[newName]);     //guanguan
複製代碼

2.3 Object.keys()

返回一個數組中包含全部屬性名(全部的key值)。

let person = {
    name : 'xiaohuanggua',
    age : 22
}
Object.keys(person);   //["name", "age"]
複製代碼

2.4 Object.values()

返回一個數組中包含全部屬性值(全部的value值)。

let person = {
    name : 'xiaohuanggua',
    age : 22
}
Object.values(person);   //["xiaohuanggua", 22]
複製代碼

刪除屬性

delete運算符

能夠刪除對象的屬性。

let person = {
    name : 'xiaohuanggua',
    age : 22
}
delete person.name;
console.log(person);   //{age: 22}
複製代碼

delete運算符只能刪除自有屬性,不能夠刪除繼承屬性(要刪除繼承屬性必須從這個屬性的原型對象上刪除)。

delete運算符不能刪除可配置項爲false的屬性。

檢測屬性

用於檢測對象成員中的所屬關係,判斷某個屬性是否存在於某個對象中。

3.1 in運算符

若是右側對象的自有屬性或者繼承屬性中包含左側屬性(字符串),則返回true,不然返回false

let person = {
    name : 'xiaohuanggua',
    age : 22
}
let test ="name" in person;
console.log(test);     //true

let test2 ="sex" in person;
console.log(test);     //false
複製代碼

3.2 hasOwnProperty()方法

用於判斷屬性是否爲對象的自有屬性,自有屬性返回true,繼承屬性返回false

let person = {
    name : 'xiaohuanggua',
    age : 22
};
person.hasOwnProperty('name');    //true person對象存在name屬性
person.hasOwnProperty("sex");     //false person對象並無這個屬性
person.hasOwnProperty("toString");   //false 這個屬性是繼承自Object對象 
複製代碼

3.3 propertyIsEnumerable()方法

只有當屬性是對象的自有屬性,且屬性的可枚舉性爲true是才爲true,不然爲false

let person = {
    name : 'xiaohuanggua',
    age : 22
};
person.propertyIsEnumerable('name'); 
//true person對象存在name屬性且可枚舉
person.propertyIsEnumerable('sex');   
//false person對象不存在sex屬性
person.propertyIsEnumerable('toString');  
//false person對象存在toString屬性,可是toString不是person的自有屬性,且不可枚舉
複製代碼

3.4 !== 操做符

判斷屬性是否爲undefined

let person = {
    name : 'xiaohuanggua',
    age : 22
};
person.name !== undefined;   //true
person.sex !== undefined;    //false
person.toString !== undefined;   //true
複製代碼

可是 !==操做符 不能區分不存在的屬性和存在可是值爲undefined的屬性,而in能夠很好地區分。

let person = {
    name : undefined,
};
// !==
person.name !== undefined;  //false 屬性存在,但值爲undefined
person.age !== undefined;   //false 屬性不存在

// in
'name' in person;    //true 屬性存在,但值爲undefined
'age' in person;     //false 屬性不存在
複製代碼

枚舉屬性

4.1 for..in

let person = {
    name : "xiaohuanggua",
    age : 22,
    sex : 'boy',
};
for(item in person){
    console.log(item);    //name,age,sex 
}
複製代碼

for in老是獲得對象的key值。

4.2 Object.keys()

得到對象全部可見屬性的屬性名(key值),不包括原型中定義屬性。

let person = {
    name : "xiaohuanggua",
    age : 22,
    sex : 'boy',
};
Object.keys(person);   //["name", "age", "sex"]
複製代碼

4.3 Object.getOwnPropertyNames()

得到對象全部屬性,不包括原型中定義屬性。

let person = {
    name : "xiaohuanggua",
    age : 22,
    sex : 'boy',
};
Object.getOwnPropertyNames(person);   //["name", "age", "sex"]
複製代碼

屬性get和set

Get:在讀取屬性時調用的函數。默認值爲 undefined

Set:在寫入屬性時調用的函數。默認值爲 undefined

let man = {
    name:'小黃瓜',
    weibo:'@xiaohuanggua',
    get age(){
        return new Date().getFullYear()-1997;
    },
    set age(val){
        console.log('我今年'+ val);
    }
}
console.log(man.age);     //22 讀取的時候調用
man.age = 1000;      //我今年1000 設置的時候調用
複製代碼

屬性類型

數據屬性和訪問器屬性。

6.1 數據屬性

數據屬性包含一個數據值的位置,在這個位置能夠讀取和寫入值。

數據屬性特性:

  1. Configurable:表示可否修改屬性的特性,可否經過 delete 刪除屬性從新從新定義屬性,或者可否把屬性修改成訪問器屬性,這個特性默認值爲 true

  2. Enumerable:表示可否經過循環返回屬性(可枚舉),這個特性默認值爲 true

  3. Writable:表示是否能夠修改屬性的值。默認值爲 true

  4. Value:包含這個屬性的數據值。讀取屬性值的時候,從這個位置讀;寫入屬性值的時候, 把新值保存在這個位置。這個特性的默認值爲 undefined

let person = { 
    name: "小黃瓜" ;
}; 
複製代碼

直接在對象上定義的屬性,它們的ConfigurableEnumerableWritable都被設置爲 true,而value特性被設置爲指定的值。

上面的例子建立了一個名爲 name 的屬性,爲它指定的值是"小黃瓜"。也就是說,value特性將 被設置爲"小黃瓜",而對這個值的任何修改都將反映在這個地方。

而若是要修改屬性默認的特性,必須使用 Object.defineProperty()方法。

這個方法接收三個參數: 屬性所在的對象、屬性的名字和一個對象。

其中,對象的屬性必須是:configurableenumerablewritablevalue

let person = {}; 
Object.defineProperty(person, "name", { 
 writable: false, 
 value: "小黃瓜" 
}); 
alert(person.name); //"小黃瓜" 
person.name = "小綠瓜"; 
alert(person.name); //"小黃瓜" 
複製代碼

咱們建立了一個名爲 name 的屬性,它的值"小黃瓜"是隻讀的。這個屬性的值是不可修改 的,若是嘗試爲它指定新值,那麼賦值操做無效。

let person = {}; 
Object.defineProperty(person, "name", { 
 configurable: false, 
 value: "小黃瓜" 
}); 
alert(person.name); //"小黃瓜" 
delete person.name; 
alert(person.name); //"小黃瓜" 
複製代碼

由於咱們將 configurable 設置爲 false,表示不能從對象中刪除屬性,因此刪除操做無效。

一旦把屬性定義爲不可配置的,就不能再把它變回可配置了。那麼再調用Object.defineProperty()方法修改除 writable 以外的特性,都會致使錯誤:

let person = {}; 
Object.defineProperty(person, "name", { 
 configurable: false, 
 value: "小黃瓜" 
}); 
//報錯!!
Object.defineProperty(person, "name", { 
 configurable: true, 
 value: "小黃瓜" 
}); 
複製代碼

6.2 訪問器屬性

訪問器屬性 gettersetter 函數(這兩個函數都不是必需的)。 在讀取訪問器屬性時,會調用 getter函數,這個函數負責返回有效的值;在寫入訪問器屬性時,會調用 setter 函數並傳入新值,這個函數負責如何處理數據。

有以下 四 個特性:

  1. Configurable:表示可否經過 delete 刪除屬性從而從新定義屬性,可否修改屬性的特 性,直接在對象上定義的屬性,這個特性的默認值爲true
  2. Enumerable:表示可否經過循環返回屬性。對於直接在對象上定義的屬性,這個特性的默認值爲 true
  3. Get:在讀取屬性時調用的函數。默認值爲 undefined
  4. Set:在寫入屬性時調用的函數。默認值爲 undefined
let person = { 
    name: '小黃瓜', 
    edition: 1 
}; 
Object.defineProperty(person, "year", { 
    get: function(){ 
        return this.name; 
    }, 
    set: function(newValue){ 
        if (newValue > 2019) { 
            this.edition = 2;
        } 
    } 
}); 

person.year = 2020; 
alert(person.edition); //2 
複製代碼

不必定非要同時指定 gettersetter。只指定 getter 意味着屬性是不可寫,寫入屬性會被忽略。

6.3 定義多個屬性

Object.defineProperties()方法。利用這個方法能夠一次定義多個屬性。

這個方法接收兩個對象參數:第一個對象是要添加和修改其屬性的對象,第二個對象的屬性與第一個對象中要添加或修改的屬性一一對應。

例如:

let person = {}; 
Object.defineProperties(person, { 
    name: { 
        value: '小黃瓜' 
    }, 
 
    edition: { 
        value: 1 
    }, 
    year: { 
        get: function(){ 
            return this.name; 
        }, 
        set: function(newValue){ 
            if (newValue > 2004) { 
               this.edition = 1;
            } 
        } 
    } 
}); 

複製代碼

person 對象上定義了兩個數據屬性(nameedition)和一個訪問器屬性(year)。 最終的對象與以前中定義的對象相同。惟一的區別是這裏的屬性都是在同一時間建立的。

6.4 讀取屬性的特性

Object.getOwnPropertyDescriptor()方法,能夠取得給定屬性的描述。

這個方法接收兩個參數:屬性所在的對象和要讀取其描述符的屬性名稱。返回值是一個對象,若是 是訪問器屬性,這個對象的屬性有 configurableenumerablegetset;若是是數據屬性,這個對象的屬性有 configurableenumerablewritablevalue

let person = {}; 
Object.defineProperties(person, { 
    name: { 
        value: '小黃瓜' 
    }, 
 
    edition: { 
        value: 1 
    }, 
    year: { 
        get: function(){ 
            return this.name; 
        }, 
        set: function(newValue){ 
            if (newValue > 2004) { 
               this.edition = 1;
            } 
        } 
    } 
}); 

let descriptor = Object.getOwnPropertyDescriptor(person, "name"); 
alert(descriptor.value); //小黃瓜 
alert(descriptor.configurable); //false 
alert(typeof descriptor.get); //"undefined"

let descriptor = Object.getOwnPropertyDescriptor(person, "year"); 
alert(descriptor.value); //undefined 
alert(descriptor.enumerable); //false 
alert(typeof descriptor.get); //"function" 
複製代碼

序列化對象

對象有兩個方法:stringify()parse()。這兩個方法分別用於把 JavaScript 對象序列化爲 JSON 字符串和把 JSON 字符串解析爲原生 JavaScript 值。

//對象轉字符串
let obj = {x:1,y:true,z:[1,2,3],nullVal:null};
JSON.stringify(obj);     //"{"x":1,"y":true,"z":[1,2,3],"nullVal":null}"

//若是存在undefined,則不會出現序列化中
let obj = {val:undefined,a:NaN,b:Infinity,c:new Date()};
JSON.stringify(obj);       //"{'a':null,'b':null,'c':2019-06-20T10:32:34}"

//字符串轉對象
let obj = JSON.parse('{"x":1}');
obj.x;     //1
複製代碼

對象的屬性

每個對象都有與之相關的原型(proto)、類(class)、可擴展性(extensible)。這就是對象的三個屬性。

原型屬性

  經過對象字面量的方式建立的對象使用Object.prototype做爲它們的原型;

  經過new建立的對象使用構造函數的prototype屬性來做爲它們的原型;

  經過Object.create()來建立的對象使用第一個參數做爲它們的原型。

//想要檢測一個對象是不是另外一個對象的原型(或者處於原型鏈中),使用isPrototypeOf()方法。
    let person = {x:1,y:2};
    let newPerson = Object.create(person);
    person.isPrototypeOf(newPerson);//true
    Object.prototype.isPrototypeOf(newPerson);//true
複製代碼

類屬性

用於表示信息對象類型。 只能經過toString()這種方法查詢對象的類信息。該方法返回以下格式的字符串: [object class]。接着提取字符串的第八個到倒數第二個位置之間的字符獲得類信息。

  1. 經過內置構造函數建立的對象,其類屬性與構造函數的名稱相匹配。

  2. 經過對象字面量和Object.create建立的對象的類屬性是 Object

  3. 自定義構造函數建立的對象的類屬性也是Object

可擴展屬性

用以表示是否能夠向對象添加新屬性。

(詳情見屬性類型)

對象方法

9.1 toString()方法

toString() 方法可用於將當前對象轉換爲字符串形式,並返回結果。

//Object
    let person = {name:'小黃瓜',age:1000};
    console.log(person.toString()); //[object Object]
//Array
    let array = ["小黃瓜", true, 12, -5];
    console.log(array.toString()); //小黃瓜,true,12,-5
複製代碼

9.2 toLocaleString() 方法

toLocaleString() 方法返回一個表示這個對象的本地化字符串。可根據本地時間把 Date 對象轉換爲字符串,並返回結果。

let date = new Date();
console.log(date.toLocaleString()); //2019/8/11 下午11:51:09
複製代碼

9.3 valueOf() 方法

valueOf() 方法用於返回指定對象的原始值。

// Array:返回數組對象自己
let array = ["小黃瓜", true, 12, -5];
console.log(array.valueOf());  //["小黃瓜", true, 12, -5]
console.log(array.valueOf() === array ); // true

// Object:返回對象自己
let person = {name: "小黃瓜", age: 18};
console.log(person.valueOf()); //{name: "小黃瓜", age: 18}
console.log(person.valueOf() === person ); // true
複製代碼

9.4 toJSON()方法

toJSON()方法返回其自身的 JSON 數據格式。

//原生 Date 對象 toJSON()方法
let d=new Date();
let n=d.toJSON();
console.log(n);  //2019-08-11T16:19:52.681Z

//任何對象添加 toJSON()方法
 let book = { 
    "title": "Professional JavaScript", 
     "authors": [ 
        "Nicholas C. Zakas" 
    ], 
    edition: 3, 
    year: 2011, 
    toJSON: function(){ 
        return this.title; 
    } 
 }; 
 
let jsonText = JSON.stringify(book); 
console.log(jsonText);  //"Professional JavaScript"
複製代碼

toJSON()能夠做爲函數過濾器的補充。假設把一個對象傳入JSON.stringify(),序列化該對象的順序以下:

1. 若是存在 toJSON()方法並且能經過它取得有效的值,則調用該方法。不然,返回對象自己。
2. 若是提供了第二個參數,應用這個函數過濾器。傳入函數過濾器的值是第一步返回的值。
3. 對第二步返回的每一個值進行相應的序列化。
4. 若是提供了第三個參數,執行相應的格式化。
複製代碼

關於對象的上半部分已經完結,下一篇還會遠嗎.....

本文參考:

Javascript高級程序設計(第三版)

Javascript權威指南(第六版)

相關文章
相關標籤/搜索