前端基礎

-

新手學 JavaScript - 物件 object 基礎觀念,甚麼是物件?如何創建物件?

this.web

物件不只是 JavaScript 裡的觀念,而是整個軟體程式語言都會接觸到的名詞。

物件是什麼?

可以把物件想像成一個容器,裡面有很多 key (鍵),每個 key (鍵) 也會有對應的 value (值)。

舉個例子,一個人就可以是一個物件,因為一個人會有名字、年齡、職業...等等資訊,這些資訊的名字和內容就可以組和成一個物件,比如說:

let person1 = {
  name: 'thisWeb',
  age: 18,
  job: 'Front-end Engineer'
}

上面我們創建了一個 person1 物件,物件裡有name、age、job等資訊,這些資訊又叫做物件的屬性

很多東西都可以用物件表示,例如車子也可以是一個物件,我們在網頁上註冊的會員資料可以是一個物件,所以在 JS 裡,物件是很重要且常見的東西。

創建物件的方法

在JS裡有兩個常用來創建物件的方法,第一種是先創建一個空白的物件,在塞入各種資料給他:

let person1 = new Object();
person1.name = 'thisWeb';
person1.age = 18;
person1.job = 'Front-end Engineer';

但這種方法不常使用,更常用的是向一開始的例子,用大括號 {} 來創建,因為更簡潔:

let person1 = {
  name: 'thisWeb',
  age: 18,
  job: 'Front-end Engineer'
}

( 這個方法又稱 Object literal,台灣的翻譯叫物件實字,對岸的翻譯叫物件字面量,不是很重要,有印象就好 )

當然,物件裡面也可以放函式(function)

let person1 = {
  name: 'thisWeb',
  age: 18,
  job: 'Front-end Engineer'
  sayName: function() {
    console.log(this.name) // 這裡的this是指person1這個物件
  }
}

物件裡放函式也可以簡寫成這樣,省略 : function :

let person1 = {
  name: 'thisWeb',
  age: 18,
  job: 'Front-end Engineer'
  sayName() {
    console.log(this.name) // 這裡的this是指person1這個物件
  }
}

那物件裡有這些資料後,要如何取得或使用呢?

如何取得物件裡的值(資料)?

第一種方式是利用 物件名字.屬性名字 就可以取得物件屬性的值:

console.log(person1.age) // 18

呼叫函式的方法也是類似的:

person1.sayName() // 'thisWeb'

第二種方式比較少用,是用 [屬性名字] 來調用

console.log(person1['age']) // 18
person1['sayName']() // 'thisWeb'

這種方式要打的字比較多,函式調用看起來也很複雜,所以更推薦第一種用法喔。

物件裡的 this 是什麼?

前面有段程式碼寫了 this.name,這個 this 是什麼意思呢?

其實很簡單 this 就是指這個物件本身:

let person1 = {
  name: 'thisWeb',
  age: 18,
  job: 'Front-end Engineer'
  sayName: function() {
    console.log(this.name) // 相當於 person1.name
  }
}

使用 this 的好處是,如果有多個物件時,就可以分別使用它的各自的屬性,例如我們現在多了 person2 物件:

let person2 = {
  name: '請網這邊走',
  age: 15,
  job: 'student'
  sayName: function() {
    console.log(this.name) 
  }
}

person1.sayName() // thisWeb
person2.sayName() // 請網這邊走

更好創建物件的模式

不知道你有沒有想過一個問題,如果我們要創建100個人,難道要一個一個打嗎,會累鼠掉吧,所以我們可以用一些設計模式,來更輕鬆的創造物件。

分別為:

  1. 工廠模式
  2. 構造函數模式

在開始之前,要記得這些模式都是一種設計方法,並不是一個新的語法或函式,他是只是方法。

工廠模式

工廠模式就是把每個函數當成一個工廠,在工廠內部自己創建一個物件,並且輸出物件 👇

function createPerson(name, age, job) {
  let o = new Object();
  o.name = name;
  o.age = age;
  o,sayName = function() {
    console.log(this.name)
  };
  return o;
}

let person1 = createPerson("Jack", 20, "webDeveloper");
let perons2 = createPerson("Rose", 22, "webDesign");

上面的例子可以看出這個工廠是來造人的,可以重複造出好多類似的人。

雖然解決了創建多個類似對象的問題,不過他有個小問題,就是我們沒辦法很好的去識別對象是什麼類型。

就像上面的例子,除非看程式碼,不然無法判斷說 Jack 到底是人還是車子,所以有了接下來的構造函式

構造函式模式

如果你還記得的話,宣告陣列的其中一個方法是 let arr = new Array(),宣告物件也有一個方式是 let obj = new Object()ObjectArray 就是JS內建的原生構造函式,我們也可以自定義一個構造函式,像是:

function Person(name, age, job) {
	this.name = name;
	this.age = age;
	this.job = job;
	this.sayName() {
		console.log(name)	
	}
}

let person1 = new Person('Jack', 18, 'web develope');
let person2 = new Person('Rose', 22, 'web designer');

console.log(person1.constructor === Person) // true
console.log(person2.constructor === Person) // true

console.log(person1 instanceof Object) // true
console.log(person1 instanceof Person) // true

你可以發現我們能用 constructorinstanceof 來識別對象的類型,通常認為 instanceof 是確定對象類型比較可靠的方式。

如果有一個物件是用 Person 創造出來的,就稱這個物件為 Person 的實體、實例(instance)

也要注意,構造函式習慣用大寫開頭,這樣有助於後人來分別是構造函式還是普通函式。

構造函式的特性

構造函式仍然是一個函式,他並不是一個 JS 裡特殊的語法,任何函數只要使用 new 操作調用就是構造函式,不使用 new 就是普通函數:

function Person(name, age) {
  this.name = name;
  this.age = age;
  this.sayName = function() {
    console.log(this.name)
  }
}
let person1 = new Person('Jack', 18) // 作為構造函式使用
Person('Rose', 20); // 作為普通函式使用
window.sayName(); // "person1" 添加到 window 中

構造函式的問題

構造函式的優點前面說完了,該來說說問題了!在構造函式裡面宣告的函數,會在每一個用構造函數式創建的物件(稱為實例)上都宣告一次,造成資源的浪費:

function Person(name, age, job){ 
 this.name = name; 
 this.age = age; 
 this.job = job; 
 this.sayName = function() {console.log(this.name)}; 
}

console.log(person1.sayName == person2.sayName); // false

有沒有發現一樣功能的函式重複宣告了,造成資源的浪費!所以我們用原型(prototype)來解決這個問題。

原型就像一個大倉庫,讓每個實例都可以來倉庫共用一些資源。

function  Person(name, age) {
	this.name = name;
	this.age = age;
  
  // 將 sayName 放到 prototype 原型上
	Person.prototype.sayName = function() {
    console.log(this.name)
  }
}

let person1 = new Person('Jack', 20); 
person1.sayName(); // "Jack" 
let person2 = new Person('Rose', 22); 
person2.sayName(); // "Rose" 
console.log(person1.sayName == person2.sayName); // true

這樣就很好解決資源浪費的問題了!

小結

今天介紹了 JS 裡的物件和創建物件的方法、模式,最常使用的是構造函式,基本上構造函式用於創建和初始化物件,並且通常使用關鍵字 "new" 來調用。

雖然構造函式很好用,但它仍然有一個問題,就是會重複宣告功能相同的函式,造成資源的浪費,所以需要原型 prototype 來解決這個問題,有關原型的深入話題就讓我們留到下次說吧!

今天就這樣,下次見囉!

相關系列文章