# 章節(jié)導(dǎo)航
[TOC]
### [介紹](https://www.theodinproject.com/courses/javascript/lessons/objects-and-object-constructors#introduction)
在我們的JavaScript基礎(chǔ)課程中,您應(yīng)該已經(jīng)學(xué)習(xí)了[使用對象](https://www.theodinproject.com/courses/web-development-101/lessons/fundamentals-part-5)來存儲和檢索數(shù)據(jù)的[基礎(chǔ)知識](https://www.theodinproject.com/courses/web-development-101/lessons/fundamentals-part-5)。讓我們先來回顧一下吧。
有多種方法可以定義對象,但在大多數(shù)情況下,最好使用**對象文字**語法,如下所示:
~~~javascript
const myObject = {
property: 'Value!',
otherProperty: 77,
"obnoxious property": function() {
// do stuff!
}
}
~~~
還有兩種方法可以從對象中獲取信息:點表示法和括號表示法。
~~~javascript
// dot notation
myObject.property // 'Value!'
// bracket notation
myObject["obnoxious property"] // [Function]
~~~
您使用哪種方法取決于上下文。點符號更清晰,通常是首選,但有很多情況下無法使用它。例如,`myObject."obnoxious property"`將無法工作,因為該屬性是一個包含空格的字符串。同樣,您不能在點表示法中使用變量:
~~~javascript
const variable = 'property'
myObject.variable // this gives us 'undefined' because it's literally looking for a property named 'variable' in our object
myObject[variable] // 'Value!'
~~~
如果您對使用對象感到生氣,現(xiàn)在可能是回顧并查看我們的JavaScript 101課程中[**基礎(chǔ)5中**](https://www.theodinproject.com/courses/web-development-101/lessons/fundamentals-part-5)的內(nèi)容的好時機(jī)。
### [對象作為設(shè)計模式](https://www.theodinproject.com/courses/javascript/lessons/objects-and-object-constructors#objects-as-a-design-pattern)
您可以開始組織代碼的最簡單方法之一是將事物分組到對象中。從“tic tac toe”游戲中獲取這些示例:
~~~javascript
// example one
const playerOneName = "tim"
const playerTwoName = "jenn"
const playerOneMarker = "X"
const playerTwoMarker = "O"
// example two
const playerOne = {
name: "tim",
marker: "X"
}
const playerTwo = {
name: "jenn",
marker: "O"
}
~~~
乍一看,第一個看起來并不那么糟糕......它實際上比使用對象的示例需要更少的行,但好處是巨大的!讓我來證明:
~~~javascript
function printName(player) {
console.log(player.name)
}
~~~
這是您在示例一設(shè)置時無法做到的事情。相反,每次你想要打印特定玩家的名字時,你必須記住正確的變量名,然后手動輸入`console.log`:
~~~javascript
console.log(playerOneName)
console.log(playerTwoName)
~~~
再說一次,這并不是*那么*糟糕......但如果你*不知道*你想要打印哪個球員的名字怎么辦?
~~~javascript
function gameOver(winningPlayer){
console.log("Congratulations!")
console.log(winningPlayer.name + " is the winner!")
}
~~~
或者,如果我們不是制作2人游戲,而是更復(fù)雜的東西,例如具有大量庫存的在線購物網(wǎng)站,該怎么辦?在這種情況下,使用對象來跟蹤項目的名稱,價格,描述和其他事情是唯一的方法。不幸的是,在那種情況下手動輸入我們對象的內(nèi)容也是不可行的。我們需要一種更清潔的方式來創(chuàng)建我們的對象,這將我們帶到......
### [對象構(gòu)造函數(shù)](https://www.theodinproject.com/courses/javascript/lessons/objects-and-object-constructors#object-constructors)
如果您需要像我們的播放器或庫存項目那樣復(fù)制特定類型的對象,則創(chuàng)建它們的更好方法是使用對象構(gòu)造函數(shù),該函數(shù)看起來像這樣:
~~~javascript
function Player(name, marker) {
this.name = name
this.marker = marker
}
~~~
通過使用關(guān)鍵字調(diào)用函數(shù)來使用它`new`。
~~~javascript
const player = new Player('steve', 'X')
console.log(player.name) // 'steve'
~~~
就像使用Object Literal方法創(chuàng)建的對象一樣,您可以向?qū)ο筇砑雍瘮?shù):
~~~javascript
function Player(name, marker) {
this.name = name
this.marker = marker
this.sayName = function() {
console.log(name)
}
}
const player1 = new Player('steve', 'X')
const player2 = new Player('also steve', 'O')
player1.sayName() // logs 'steve'
player2.sayName() // logs 'also steve'
~~~
### [行使](https://www.theodinproject.com/courses/javascript/lessons/objects-and-object-constructors#exercise)
編寫一個用于制作“book”對象的構(gòu)造函數(shù)。我們將在本課結(jié)束時重新審視這個項目。你的書的對象應(yīng)該有這本書的`title`,`author`,數(shù)量`pages`,以及你是否有`read`這本書
將函數(shù)放入可以報告書籍信息的構(gòu)造函數(shù)中
~~~javascript
book.info() // "The Hobbit by J.R.R. Tolkien, 295 pages, not read yet"
~~~
注意:幾乎*總是*最好的`return`事情,而不是`console.log()`直接進(jìn)入功能。在這種情況下,返回`info`字符串并在調(diào)用函數(shù)后記錄它:
~~~javascript
console.log(theHobbit.info());
~~~
### [原型](https://www.theodinproject.com/courses/javascript/lessons/objects-and-object-constructors#the-prototype)
在我們進(jìn)一步深入研究之前,您需要了解有關(guān)JavaScript對象的重要信息。JavaScript中的所有對象都有`prototype`。簡單地說,原型是原始對象*繼承的*另一個對象,也就是說,原始對象可以訪問其原型的所有方法和屬性。
這個概念很重要,所以你有一些閱讀要做。在繼續(xù)之前確保你真的得到了這個!
1. [本文](http://javascriptissexy.com/javascript-prototype-in-plain-detailed-language/)是對該概念的直接介紹和演示。它還包括施工人員..審查的好時機(jī)!這里的重要部分,一旦你涵蓋了基礎(chǔ)知識,就是'基于原型的繼承'和'原型鏈'
2. 要更深入地了解鏈和繼承,花一些時間來閱讀[這篇偉大的文章](http://javascript.info/prototype-inheritance)。像往常一樣,最后做練習(xí)將有助于鞏固你的思想。不要跳過它們!重要提示:本文`__proto__`一般不推薦大量使用。這里的概念是我們目前正在尋找的。我們很快將學(xué)習(xí)另一種方法來設(shè)置原型。
如果您已經(jīng)理解了原型的概念,那么關(guān)于構(gòu)造函數(shù)的下一部分將不會讓人感到困惑!
~~~javascript
function Student(name) {
this.name = name
this.grade = grade
}
Student.prototype.sayName = function() {
console.log(this.name)
}
Student.prototype.goToProm = function() {
// eh.. go to prom?
}
~~~
如果您正在使用構(gòu)造函數(shù)來創(chuàng)建對象,則最好在該`prototype`對象上定義函數(shù)。這樣做意味著將在所有Student對象之間共享每個函數(shù)的單個實例。如果我們在構(gòu)造函數(shù)中直接聲明函數(shù),就像我們在第一次引入它時所做的那樣,每次創(chuàng)建一個新學(xué)生時,該函數(shù)都會被復(fù)制。在這個例子中,這并不重要,但在一個創(chuàng)建數(shù)千個對象的項目中,它確實可以產(chǎn)生影響。
#### 推薦的原型繼承方法
到目前為止,您已經(jīng)看到了幾種使對象從另一個對象繼承原型的方法。在歷史的這一點上,建議設(shè)置對象原型的方法是`Object.create`([這里](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create)是該方法的文檔。)`Object.create`非常簡單地返回一個具有指定原型的新對象以及要添加的任何其他屬性。出于我們的目的,您可以這樣使用它:
~~~javascript
function Student() {
}
Student.prototype.sayName = function() {
console.log(this.name)
}
function EighthGrader(name) {
this.name = name
this.grade = 8
}
EighthGrader.prototype = Object.create(Student.prototype)
const carl = new EighthGrader("carl")
carl.sayName() // console.logs "carl"
carl.grade // 8
~~~
你可以弄清楚這里發(fā)生了什么。在為EighthGrader創(chuàng)建構(gòu)造函數(shù)之后,我們將它的原型設(shè)置為一個具有副本的新對象`Student.prototype`。
警告......這不起作用:
~~~javascript
EighthGrader.prototype = Student.prototype
~~~
因為它會將EighthGrader的原型設(shè)置為Student.prototype(即不是副本),如果您想在將來編輯某些內(nèi)容,可能會導(dǎo)致問題。再考慮一個例子:
~~~javascript
function Student() {
}
Student.prototype.sayName = function() {
console.log(this.name)
}
function EighthGrader(name) {
this.name = name
this.grade = 8
}
// don't do this!!!
EighthGrader.prototype = Student.prototype
function NinthGrader(name) {
this.name = name
this.grade = 9
}
// noooo! not again!
NinthGrader.prototype = Student.prototype
NinthGrader.prototype.sayName = function() {console.log("HAHAHAHAHAHA")}
const carl = new EighthGrader("carl")
carl.sayName() //uh oh! this logs "HAHAHAHAHAHA" because we edited the sayName function!
~~~
如果我們`Object.create`在這個例子中使用過那么我們可以安全地編輯`NinthGrader.prototype.sayName`函數(shù)而不改變函數(shù)`EighthGrader`。
- 前言
- 你真的懂This嗎?
- 對象和對象構(gòu)造函數(shù)
- 工廠功能和模塊模式
- API的使用
- async and await
- 關(guān)于async的很棒的一篇文章
- 掘金:關(guān)于forEach,map,fiter循環(huán)操作
- Node.js 實例與基礎(chǔ)
- 原創(chuàng): Express 學(xué)習(xí)使用筆記
- 零碎知識點方法
- 關(guān)于滾動吸頂?shù)姆椒?/a>
- Vue學(xué)習(xí)筆記
- Vue向?qū)?/a>
- vuex是啥?
- vue代碼風(fēng)格指南
- 關(guān)于vue的初體驗
- 超詳細(xì)解毒Vue
- Vue實例
- 模版語言
- 組件基礎(chǔ)
- 條件渲染、列表渲染、Class與style綁定
- Todolist的制作超詳細(xì)
- vue-router
- Vue基礎(chǔ)2.0x 筆記
- 搭建vuepress
- JavaScript之ES6
- 箭頭函數(shù)
- 這就是This
