前言
- 學習物件導向時我們常說“萬物皆物件”,當然在JavaScript中也不例外。不誇張地說:沒有理解物件,就無法理解JavaScript。本文將向你展現物件的詳細內容,希望對你有幫助。
1. 物件的定義
1.1 “萬物皆物件”一探究竟
1.1.1 都是物件
-
布林型別通過new Boolean()建立時是物件
-
數字型別通過new Number()建立時是物件
-
字串型別通過new String()建立時是物件
-
Date、Math、Array、RegExp本身就是物件
-
函式用typeof檢測返回的是“function”,但其有屬性和方法,也像是物件(函式通過new Function()建立時是物件)
-
Object是物件的物件
1.1.2 也有例外
-
原始資料型別有 number、boolean、string、null、undefined
-
其中null也是物件型別
typeof true //boolean
typeof 123 //number
typeof "str" //string
typeof undefined //undefined
typeof null //object
複製程式碼
1.1.3 結論:
-
原始資料型別的number、boolean、string、undefined不是物件型別
-
function關鍵字建立的函式不是物件型別
-
其餘都是物件型別
1.2 到底什麼是物件?
- 首先看看下面的物件定義
var Person = {
name: "一燈",
age: 23,
task: function() {
console.log('寫程式碼!')
}
}
複製程式碼
- 是不是很像變數的定義呢?
var name = "一燈"
複製程式碼
-
實際上,物件就是一個變數,變數即是一個容器,只不過物件這個容器可以裝各種型別的資料,而普通變數只能裝某種型別的資料。
-
可以把物件理解為一個超級變數。
1.3 物件的屬性和方法
-
剛說到物件是一個容器,裡面裝的就是屬性和方法
-
方法:即物件裡面定義的函式,如上面的task函式
-
屬性:除了方法,其餘的都是屬性,如上面的name屬性
1.4 建立物件的方式(這裡不作詳細討論)
-
通過字面量建立(最簡單的),即上面的那種
-
通過new Object()
var Person = new Object()
Person.name = "一燈"
Person.age = 23
Person.task = function() {
console.log('寫程式碼!')
}
複製程式碼
-
通過建構函式
-
通過Object.create()
1.5 物件的賦值
- 先看看普通變數的賦值
var a = 10
var b = a
var b = 20
console.log(a) //a = 10,b的改變不會影響a
複製程式碼
- 物件賦值會怎樣呢?
var Person = {
name: "一燈",
age: 23,
}
var a = Person
a.age = 24
console.log(Person.age) //Person.age = 24,受到了a的影響
複製程式碼
- 結論:物件的“賦值”不是賦值,而賦的是地址,兩個物件指向了同一個地址,因此會相互影響。
2. 屬性
2.1 屬性的訪問方式
- objectName.property
- objectName["property"] (注意加引號)
- objectName[表示式] (表示式的結果必須是一個屬性名,本質和第2種是一樣的)
//1
Person.age
//2
objectName["age"]
//3
var a = "age"
objectName[a]
複製程式碼
2.2 for...in遍歷屬性
var Person = {
name: "一燈",
age: 23,
tel: 123456
}
var str = ''
for (x in Person) {
str += Person[x]+" ";
}
console.log(str) //一燈 23 123456
複製程式碼
2.3 新增屬性
- 可以給一個已定義的物件新增屬性
var Person = {
name: "一燈",
age: 23
}
Person.tel = 123456
console.log(Person) //{ name: '一燈', age: 23, tel: 123456 }
複製程式碼
- 若屬性已經存在,則會修改屬性
var Person = {
name: "一燈",
age: 23
}
Person.age = 24
console.log(Person) //{ name: '一燈', age: 24 }
複製程式碼
2.4 刪除屬性
- 可通過delete關鍵字刪除屬性
var Person = {
name: "一燈",
age: 23
}
delete Person.age
console.log(Person) //{ name: '一燈' }
複製程式碼
- 使用delete需要知道的幾點:
- 屬性值和屬性本身都會被刪除,刪除後不可再使用,除非再次新增該屬性
- delete僅用於刪除物件屬性,對其他無效
- 切記不要刪除物件中不存在的屬性,以免程式崩潰
- delete不會刪除繼承的屬性
2.5 屬性的屬性
- 是的,你沒有看錯,物件的屬性也是有屬性的,屬性值只是其中一個屬性
- 物件屬性還有其他三個屬性:可列舉、可配置、可讀寫,後面會介紹如何操作這些屬性
3. 方法
3.1 this關鍵字(注意:這裡是指物件方法中的this,關於this單獨講)
- 指的是方法的所有者,即該方法隸屬的物件(下面例子中this隸屬於person物件)
var person = {
name: "一燈",
age: 23,
show: function() {
console.log("Hello" + this.name)
}
}
person.show() //Hello一燈
複製程式碼
3.2 方法的訪問
- 方法通過 objectName.methodName() 的形式訪問,如上面的例子:person.show()
3.3 新增方法
person.info = function () {
return this.name + "-" + this.age
}
複製程式碼
4. 訪問器
- 可通過 getter 和 setter 操作物件訪問器
4.1 getter(使用get關鍵字)
var person = {
name: "一燈",
age : 23,
get getName() {
return this.name;
}
}
console.log(person.getName) //一燈
複製程式碼
4.2 setter(使用set關鍵字)
var person = {
name: "一燈",
age : 23,
set setName(name) {
this.name = name;
}
}
person.setName = "111"
console.log(person.name) //111
複製程式碼
4.3 函式 VS 訪問器
- 你已經發現了,這種方式似乎和函式很像
//函式實現getter
var person = {
name: "一燈",
age : 23,
getName: function() {
return this.name;
}
}
//getter:console.log(person.getName),語法更簡潔
console.log(person.getName()) //一燈
//函式實現setter
var person = {
name: "一燈",
age : 23,
setName: function(name) {
this.name = name;
}
}
//setter:person.setName = "111",語法和操作屬性一樣
person.setName(111)
console.log(person.name) //111
複製程式碼
-
對比發現: 訪問器屬性語法更簡潔,並且方法和屬性的操作一致
-
值得注意的一點:訪問器屬性對錯誤不那麼敏感
//setter
var person = {
name: "一燈",
age : 23,
set setName(name) {
this.name = name;
}
}
person.sdetName = "111" //setName拼錯,但是沒有報錯
console.log(person.name)
//函式
var person = {
name: "一燈",
age : 23,
setName: function(name) {
this.name = name;
}
}
person.sdetName(111) //setName拼錯,報錯了
console.log(person.name)
複製程式碼
4.4 Object.defineProperty()
- 新增訪問器屬性的另一種方式,通過Object.defineProperty(),格式如下:
var person = {
name: "一燈",
age: 23
}
//getter
Object.defineProperty(person, "getName", {
get: function() {
return this.name
}
})
console.log(person.getName) //一燈
//setter
Object.defineProperty(person, "setName", {
set: function(name) {
return this.name = name
}
})
person.setName = 111
console.log(person.name) //111
複製程式碼
5. 建構函式
-
JavaScript採用構造的函式建立物件是一種常見的方法,通常採用首字母大寫的駝峰法命名物件
-
然後通過new關鍵字建立物件例項
function Person(name, age) {
this.name = "一燈",
this.age = 23,
this.show = function() {
console.log(this.name + '-' +this.age)
}
}
var person = new Person('一燈', 23)
person.show() //一燈-23
複製程式碼
5.1 this關鍵字
- this關鍵字隸屬於通過建構函式建立的例項,上面的例子this指向person物件
5.2 新增屬性和方法到物件
//新增屬性
person.tel = 123456
//新增方法
person.task = function() {
console.log("寫程式碼!")
}
複製程式碼
5.3 新增屬性和方法到建構函式
- 向建構函式新增屬性和方法與物件中不同,像這樣Person.tel = 123456 是無效的
- 只能在建構函式中新增
function Person(name, age) {
this.name = "一燈",
this.age = 23,
this.tel = 123456, //新增的屬性
this.show = function() {
console.log(this.name + '-' +this.age)
},
this.task = function() { //新增的方法
console.log("寫程式碼!")
}
}
複製程式碼
5.4 內建的建構函式
- 即我們熟悉的Object、Function、Array、Date、RegExp、String、Boolean、Number
- 注意:Math()是一個全域性物件,不能使用new
- **特別注意:**雖然有原始資料型別(boolean、number等等)的物件版本,但儘量避免使用new 的方式建立,使用原始值會更快。
6. 原型prototype
-
js中所有物件都從原型中繼承屬性和方法,原型是非常重用的概念
-
上一章節說到,向建構函式中新增屬性或方法需要在建構函式中新增。還有一種方式是:通過原型
function Person(name, age) {
this.name = "一燈",
this.age = 23,
this.show = function() {
console.log(this.name + '-' +this.age)
}
}
Person.prototype.tel = 123456
Person.prototype.task = function() {
console.log("寫程式碼!")
}
var person = new Person()
console.log(person.tel) //123456
person.task() //寫程式碼!
複製程式碼
- 關於原型/原型鏈的詳細內容戳這裡