Johnson Mao

Day.20 「初步認識 this,中央工廠式的自訂物件~」 —— JavaSript 構造函式

Day.20 「初步認識 this,中央工廠式的自訂物件~」 —— JavaSript 構造函式

如同學習函式一樣!有時候我們會一直重複地做一件事, 當還是初學者的我們需要製作大量的個人資料物件時,通常第一個想法就是複製貼上~

複製成功!
const person = {
  name: "毛毛",
  gender: "男",
  sayName: function() {
    console.log( "大家好!我是" + person.name );
  }
}
const person2 = {
  name: "小黃",
  gender: "男",
  sayName: function() {
    console.log( "大家好!我是" + person2.name );
  }
}
/* ... */

一直重複製作一樣的東西! 我們要發揮工程師的精神~看到一直有重複的程式碼時,就要想辦法簡化它。 在學習自訂物件之前,要先認識之前函式沒說到的「this

#this

瀏覽器在執行函式時,都會向函式傳遞一個隱藏的參數

當然這只是稍微認識了我們的 this,不過以目前的知識量,就能夠的自訂物件了!

#利用函式新增物件

我們前面有說過,函式非常方便,可以把功能都寫在函式裡,例如我們現在要來自定義物件

複製成功!
function createPerson() {
  var obj = new Object;  // 新增一個物件
  obj.name = "毛毛",
  obj.gender = "男",
  obj.sayName = function() {
    console.log( "大家好!我是" + this.name );
  }
  return obj;
}
const person = createPerson();
console.log( person );
/*
   {
      name: "毛毛",
      gender: "男",
      sayName: function() {
        console.log( "大家好!我是" + this.name );
      }
   }
*/

但會發現這樣新增的物件的是固定的! 這時我們利用函式的參數,就可以簡化新增物件的步驟了。

複製成功!
function createPerson (name, gender) {
  var obj = new Object;  // 新增一個物件
  obj.name = name,
  obj.gender = gender,
  obj.sayName = function() {
    console.log( "大家好!我是" + this.name );
  }
  return obj;
}
const person = createPerson("毛毛", "男");
const person2 = createPerson("小黃", "男");
person.sayName();  // "大家好!我是毛毛"
person2.sayName();  // "大家好!我是小黃"

但如果這個時候~還想要自訂一個寵物的物件,這樣直接看會覺得 人的物件 與 寵物的物件 差不多。

複製成功!
function createPet (name, sex, animal) {
  var obj = new Object;  // 新增一個物件
  obj.name = name,
  obj.sex = sex,
  obj.animal = animal
  return obj;
}
const pet = createPet("小黃", "雄性", "小狗");
console.log( pet );   // {...}
console.log( person ) // {...} 

這時使用建構函式來真正意義上的自訂物件,更加方便快速簡單!

#構造函式

自訂一個構造函式,用來專門新增人的物件

複製成功!
function Person () {}

普通函式是直接調用,而構造函式是透過 new 關鍵字調用!

複製成功!
const 直接調用 = Person()
const 構造函式 = new Person()
console.log( 直接調用 );  // undefined
console.log( 構造函式 );  // {}

直接調用的函式,因為沒有使用 return ,所以會自動返回 undefined

#構造函式執行過程

  1. 會立刻自動新增一個物件
  2. 函式的 this 會指向該物件
  3. 逐行執行程式碼(我們操作的部分)
  4. 將新增的物件作為返回值返回
複製成功!
function Person (name, gender) {
  this.name = name,
  this.gender = gender,
  this.sayName = function() {
    console.log( "大家好!我是" + this.name );
  }
}
const person = new Person("毛毛", "男");
console.log( person )  // Person {...}

這時你發現前面出現了 Person,再來用一個的寵物的構造函式。

複製成功!
function Pet (name, sex, animal) {
  this.name = name,
  this.sex = sex,
  this.animal = animal
}
const pet = new Pet("小黃", "雄性", "小狗");
console.log( person )  // Person {...}
console.log( pet )     // Pet {...}

這樣就可以透過構造函式更直觀的看同一類的物件

#構造函式實例檢查

JavaScript 有個語法 instanceof,可以用來檢查,物件是否為該構造函式新增出來的實例。

複製成功!
console.log(person instanceof Person); // true  代表是由這個構造函式創建出來的
console.log(person instanceof Pet);    // false 代表不是由這個構造函式創建出來的

#優化構造函式

我們前面的構造函式中,有為物件添加函式 sayName()

複製成功!
function Person (name, gender) {
  this.name = name,
  this.gender = gender,
  this.sayName = function() {
    console.log( "大家好!我是" + this.name );
  }
}
const person = new Person("毛毛", "男");
person.sayName();  // "大家好!我是毛毛"

而我們每新增一個物件,同時也跟著在物件內新增一個 sayName 函式

複製成功!
function Person (name, gender) {
  this.name = name,
  this.gender = gender,
  this.sayName = function() {
    console.log( "大家好!我是" + this.name );
  }
}
const person = new Person("毛毛", "男");
const person2 = new Person("小黃", "男");
console.log( person.sayName === person2.sayName );  // false  兩個 sayName 不一樣

發現 sayName 函式,彼此不相同,當新增了 10000 個 Person 物件,也會同時新增 10000 個 sayName 函式!而這 10000 個 sayName 函式其實都是一模一樣的,會為了這一模一樣的函式浪費記憶體空間!

這想當然是沒有必要的事情,我們可以讓所有物件共同使用一個函式。 直接在全局作用域定義一個 sayName 函式,在構造函式內賦值 sayName 函式,這時構造函式內找不到 sayName 函式,就會往外找 sayName 函式

複製成功!
function Person (name, gender) {
  this.name = name,
  this.gender = gender,
  this.sayName = sayName
}
function sayName() {
  console.log( "大家好!我是" + this.name );
}

const person = new Person("毛毛", "男");
const person2 = new Person("小黃", "男");
console.log( person.sayName === person2.sayName );  // true  兩個 sayName 引用同一個函式,所以一樣

當然這樣也是有缺點,就是把函式定義在全局作用域會壓縮到全局作用域的命名空間,而且多人協作的時候,也容易出問題

#總結

今天稍微介紹了 JavaScript 的 「this」,它可是 JavaScript 的精隨,少了 this 會有很多事情不能做,昨天介紹的記憶體堆疊,在使用物件型別的東西要特別注意,不然一不小心會讓瀏覽器效能變低,網頁卡卡的!

回首頁