JavaScript學(xué)習(xí)筆記整理(4):對象

2018-06-19 11:58 更新

JavaScript是面向?qū)ο缶幊蹋∣bject Oriented Programming,OOP)語言。


面對對象編程的核心思想就是是將真實世界中各種復(fù)雜的關(guān)系,抽象成一個個對象,然后由對象之間分工合作,完成對真實世界的模擬。

何為對象?

對象是單個實物的抽象。
一本書、一輛汽車、一個人都可以是“對象”,一個數(shù)據(jù)庫、一張網(wǎng)頁也可以是“對象”。世界上所有的對象都可以是“對象”。

對象是一個容器,封裝了“屬性”(property)和“方法”(method)。

屬性,就是對象的狀態(tài),而方法,就是對象的行為。比如:我們可以把一輛汽車抽象成一個對象,它的屬性就是它的顏色、重量等,而方法就是它可以啟動、停止等。

1、對象

在Javascript中,對象是一個基本數(shù)據(jù)類型。


對象是一種復(fù)合值:它將很多值集合在一起,可通過名字訪問這些值。對象也可看做一種無序的數(shù)據(jù)集合,由若干個“鍵值對”(key-value)構(gòu)成。

var o={

  name:'a'

}

上面代碼中,大括號定義了一個對象,它被賦值給變量o。這個對象內(nèi)部包含一個鍵值對(又稱為“成員”),name是“鍵名”(成員的名稱),字符串a(chǎn)是“鍵值”(成員的值)。鍵名與鍵值之間用冒號分隔。如果對象內(nèi)部包含多個鍵值對,每個鍵值對之間用逗號分隔。


鍵名:對象的所有鍵名都是字符串,所以加不加引號都可以。如果鍵名是數(shù)值,會被自動轉(zhuǎn)為字符串。


對象的每一個“鍵名”又稱為“屬性”(property),它的“鍵值”可以是任何數(shù)據(jù)類型。如果一個屬性的值為函數(shù),通常把這個屬性稱為“方法”,它可以像函數(shù)那樣調(diào)用。

var o = {

  go: function(x){

    return x+1;

  }

};

o.go(2) // 3


如果鍵名不符合標識名的條件(比如第一個字符為數(shù)字,或者含有空格或運算符),也不是數(shù)字,則必須加上引號,否則會報錯。

var o = {

  '1a' : 'a'  

}

上面的代碼中,如果鍵名'1a'不用引號引起來,就會報錯。

注意:為了避免這種歧義,JavaScript規(guī)定,如果行首是大括號,一律解釋為語句(即代碼塊)。如果要解釋為表達式(即對象),必須在大括號前加上圓括號。

2、創(chuàng)建對象
在JavaScript中,有三種方法創(chuàng)建對象

對象直接量: var o={};

關(guān)鍵字new: var o=new Object();

Object.create()函數(shù): var o=Object.create(null)

2.1對象直接量
對象直接量是由若干名/值對組成的映射表。鍵名與鍵值之間用冒號分隔。如果對象內(nèi)部包含多個鍵值對,每個鍵值對之間用逗號分隔。整個映射表用花括號括起來。
在ECMAScript 5中,保留字可以用做不帶引號的屬性名。
注意:對象直接量中的最后一個屬性后的逗號可有可無,但是在ie中,如果多了一個逗號,會報錯。 2.2通過new創(chuàng)建對象
new運算符創(chuàng)建并初始化一個新對象。關(guān)鍵字new后跟隨一個函數(shù)調(diào)用,這個函數(shù)稱做構(gòu)造函數(shù)(constructor)。

例子:

var o1 = {};

var o2 = new Object();

var o3 = Object.create(null);

上面三行語句是等價的。

對象最常見的用法是創(chuàng)建(create)、設(shè)置(set)、查找(query)、刪除(delete)、檢測(test)和枚舉(enumerate)它的屬性。 屬性包括名字(鍵名)和值(鍵值)。
屬性名可以是包含空字符串在內(nèi)的任意字符串,但對象中不能存在兩個同名的屬性。 3、屬性特性
可寫(writable attribute):可設(shè)置該屬性的值。
可枚舉(enumerable attribute):可通過for/in循環(huán)返回該屬性。
可配置(configurable attribute):可刪除或修改屬性。

4、讀取屬性
讀取對象的屬性,有兩種方法,一種是使用點運算符,還有一種是使用方括號運算符。

var o = {

  name : 'a'

}

o.name  // "a"

o['name']  //"a"

注意:數(shù)值鍵名不能使用點運算符(因為會被當成小數(shù)點),只能使用方括號運算符。

JavaScript對象是動態(tài)的,可新增屬性也可刪除屬性。但注意,我們是通過引用而非值來操作對象。

5、屬性的查詢和設(shè)置

在JavaScript中,我們可以通過點(.)或方括號([])運算符來獲取屬性的值。運算符左側(cè)應(yīng)當是一個表達式,它返回一個對象。


for...in

for...in循環(huán)用來遍歷一個對象的全部屬性。

var o = {

  name : 'a',

  age : 12

}

for(var i in o){

  console.log(o[i]

}

// "a"

// 12


查看所有屬性

查看一個對象本身的所有屬性,可以使用Object.keys方法,返回一個數(shù)組。

var o = {

  name : 'a',

  age : 12

}


Object.keys(o)  //['name','age']


刪除屬性

delete運算符可以刪除對象的屬性。

var o={

  name : 'a'

}

delete o.name  //true

o.name  //undefined

注意:delete運算符只能刪除自有屬性,不能刪除繼承屬性。

刪除一個不存在的屬性,delete不報錯,而且返回true。

只有一種情況,delete命令會返回false,那就是該屬性存在,且不得刪除。

檢測屬性

在JavaScript中,有多種方法檢測某個屬性是否存在于某個對象中。


用“!==”來判斷一個屬性是否是undefined


hasOwnPreperty()方法


propertyIsEnumerable()方法

只有檢測到是自有屬性且這個屬性的可枚舉性為true時才返回true。


in運算符

in運算符左側(cè)是屬性名(字符串),右側(cè)是對象。如果對象的自有屬性或繼承屬性中包含這個屬性就返回true。

var o = {

  name : 'a'

}

'name' in o //true


6、對象的三個屬性

每一個對象都有與之相關(guān)的原型(prototype)、類(class)和可擴展性(extensible attribute)

將對象作為參數(shù)傳入Object.getPrototypeOf()可以查詢它的原型。

檢測一個對象是否是另一個對象的原型,可以使用isPrototypeOf()方法。

7、序列化對象
對象序列化是指將對象的狀態(tài)轉(zhuǎn)換為字符串,也可將字符串還原為對象。


在JavaScript中,提供了內(nèi)置函數(shù)JSON.stringify()和JSON.parse()用來序列化和還原JavaScript對象。
NaN、Infinity和-Infinity序列化的結(jié)果是null

var o = {

  name : 'a',

  age : 12,

  intro : [false,null,'']

}

s= JSON.stringify(o)  // s {"name":"a","age":12,"intro":[false,null,""]}

p=JSON.parse(s)  // p是o的深拷貝


注意:JSON.stringify()只能序列化對象可枚舉的自有屬性。對于一個不能序列化的屬性來說,在序列化后的輸出字符串中會將這個屬性省略掉。


8、構(gòu)造函數(shù)
構(gòu)造函數(shù),是用來生成“對象”的函數(shù)。一個構(gòu)造函數(shù)可生成多個對象,這些對象都有相同的結(jié)構(gòu)。

構(gòu)造函數(shù)的特點:

函數(shù)體內(nèi)使用了this關(guān)鍵字,代表了所要生成的對象實例  

生成對象時,必需用new命令

構(gòu)造函數(shù)名字的第一個字母通常大寫。
例子:

function Car(){

  this.color = 'black';

}

var c = new Car();

上面的代碼生成了Car的實例對象,保存在變量c中。
構(gòu)造函數(shù)也可以傳入?yún)?shù):

function Car(color){

  this.color = color;

}

var c = new Car('red');

new命令本身就可以執(zhí)行構(gòu)造函數(shù),所以后面的構(gòu)造函數(shù)可以帶括號,也可以不帶括號。下面兩行代碼是等價的。

var c = new Car();

var c = new Car;

每一個構(gòu)造函數(shù)都有一個prototype屬性。

8.1 this關(guān)鍵字
this總是返回一個對象,簡單說,就是返回屬性或方法“當前”所在的對象。

this.property

上面的代碼中,this就代表property屬性當前所在的對象。

由于對象的屬性可以賦給另一個對象,所以屬性所在的當前對象是可變的,即this的指向是可變的。

var A = {

  name: '張三',

  describe: function(){

    return this.name;

  }

};

var B = {

  name: '李四'

};


B.describe = A.describe;

B.describe();

// "李四"


注意:如果一個函數(shù)在全局環(huán)境中運行,那么this就是指頂層對象(瀏覽器中為window對象)。

8.1.1 改變this指向
在JavaScript中,提供了call、apply、bind三種方法改變this的指向。
(1)funciton.prototype.call()

call(obj, arg1, arg2, ...)

第一個參數(shù)obj是this要指向的對象,也就是想指定的上下文;arg1,arg2..都是要傳入的參數(shù)。

注意:如果參數(shù)為空、null和undefined,則默認傳入全局對象。

(2)funciton.prototype.apply()

apply(obj,[arg1,arg2....])

apply()和call()方法原理類似,只不過,它第二個參數(shù)一個數(shù)組,里面的值就是要傳入的參數(shù)。

(3)function.prototype.bind()
bind方法用于將函數(shù)體內(nèi)的this綁定到某個對象,然后返回一個新函數(shù)。

bind(obj)


9、原型

9.1 原型

每一個JavaScript對象(null除外)都和另一個對象相關(guān)聯(lián),也可以說,繼承另一個對象。另一個對象就是我們熟知的“原型”(prototype),每一個對象都從原型繼承屬性。只有null除外,它沒有自己的原型對象。


所有通過對象直接量創(chuàng)建的對象都具有同一個原型對象,并可以通過JavaScript代碼Object.prototype獲得對原型對象的引用。


通過關(guān)鍵字new和構(gòu)造函數(shù)調(diào)用創(chuàng)建的對象的原型就是構(gòu)造函數(shù)的prototype屬性的值。比如:通過new Object()創(chuàng)建的對象繼承自O(shè)bject.prototype;通過new Array()創(chuàng)建的對象的原型就是Array.prototype。


沒有原型的對象為數(shù)不多,Object.prototype就是其中之一,它不繼承任何屬性。


所有的內(nèi)置構(gòu)造函數(shù)都具有一個繼承自O(shè)bject.prototype的原型。

9.2 原型鏈

對象的屬性和方法,有可能是定義在自身,也有可能是定義在它的原型對象。由于原型本身也是對象,又有自己的原型,所以形成了一條原型鏈(prototype chain)。比如,a對象是b對象的原型,b對象是c對象的原型,以此類推。

如果一層層地上溯,所有對象的原型最終都可以上溯到Object.prototype,即Object構(gòu)造函數(shù)的prototype屬性指向的那個對象。那么,Object.prototype對象有沒有它的原型呢?回答可以是有的,就是沒有任何屬性和方法的null對象,而null對象沒有自己的原型。

“原型鏈”的作用
當讀取對象的某個屬性時,JavaScript引擎先尋找對象本身的屬性,如果找不到,就到它的原型去找,如果還是找不到,就到原型的原型去找。如果直到最頂層的Object.prototype還是找不到,則返回undefined。

繼承
JavaScript對象具有“自有屬性”,也有一些屬性是從原型對象繼承而來的。
當查詢一個不存在的屬性時,JavaScript不會報錯,返回undefined。


如果對象自身和它的原型,都定義了一個同名屬性,那么優(yōu)先讀取對象自身的屬性,這叫做“覆蓋”(overiding)。


9.2.1 contructor屬性

prototype對象有一個constructor屬性,默認指向prototype對象所在的構(gòu)造函數(shù)。


9.3 操作符

(1)instanceof運算符

instanceof運算符返回一個布爾值,表示指定對象是否為某個構(gòu)造函數(shù)的實例。

var c = new Car();

c instanceof Car  //true

instanceof運算符的左邊是實例對象,右邊是構(gòu)造函數(shù)。它的運算實質(zhì)是檢查右邊構(gòu)建函數(shù)的原型對象,是否在左邊對象的原型鏈上。


(2)Object.getPrototypeOf()

Object.getPrototypeOf方法返回一個對象的原型。這是獲取原型對象的標準方法

Object.getPrototypeOf(c) === Car.prototype  //true


(3)Object.setPrototypeOf()

Object.setPrototypeOf方法可以為現(xiàn)有對象設(shè)置原型,返回一個新對象。Object.setPrototypeOf方法接受兩個參數(shù),第一個是現(xiàn)有對象,第二個是原型對象。


(4)Object.create()

Object.create方法用于從原型對象生成新的實例對象,可以替代new命令。

它接受一個對象作為參數(shù),返回一個新對象,后者完全繼承前者的屬性,即原有對象成為新對象的原型。


(5)Object.prototype.isPrototypeOf()

對象實例的isPrototypeOf方法,用來判斷一個對象是否是另一個對象的原型。

Object.prototype.isPrototypeOf({})  //true


(6)Object.prototype.__proto__

__proto__屬性(前后各兩個下劃線)可以改寫某個對象的原型對象。



(7)Object.getOwnPropertyNames()

Object.getOwnPropertyNames方法返回一個數(shù)組,成員是對象本身的所有屬性的鍵名,不包含繼承的屬性鍵名。


(8)Object.prototype.hasOwnProperty()

對象實例的hasOwnProperty方法返回一個布爾值,用于判斷某個屬性定義在對象自身,還是定義在原型鏈上。







以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號