[JS奇怪的世界]No.50 函數建構子、「new」與 JavaScript 的歷史

前言

前面我們已經瞭解許多物件、原型繼承、原型鏈和物件屬性及方法,接下將更深入討論建立物件。

「new」

前面我們已經有講過幾種建立物件的方式,其中一個是物件實體語法。

1
2
3
4
var jack = {
firstname: 'jack',
lastname: 'Dec',
}

而其實還有別的物件建立方式。

1
var jack = new Person();

那為什麼會有 new?,這主要與 JavaScript 的誕生有關係,一個語言若都沒有人使用就代表著死亡,所以當初 JavaScript 會叫 JavaScript 就是希望可以吸引 Java 開發者,而 Java 開發者習慣使用 new 的關鍵字來定義物件等等,所以當 Java 開發者看到這樣寫會感覺比較親切,但是使用這種方式來建立物件有些許問題,但是我們還是需要瞭解,因為許多專案及原始碼都會有它的存在。

下面將用課堂的範例來做一點好玩的事情。

1
2
3
4
5
6
7
8
function Person() {
this.fistname = 'John';
this.lastname = 'Doe';
}

var john = new Person();

console.log(john);

我們發現 john 變成一個物件了,但是這邊我們要記得一件事情,我們只是在利用一些方法在 JavaScript 中建立物件,那為了建立物件我們必須給它屬性和方法,然後建立原型,而這是為了讓我們看更清楚而做的,所以接下來將使用比較正確的方式來增加屬性和方法、設定原型。

new 其實是一個運算子,為什麼這樣講呢?讓我們翻一下先前的文件>MDN 的文件 (在下方一點地方)

上面的例子中 new 會改變 this 指向的東西,this 指向到一個空的物件,而 new 建立了一個新物件,然後呼叫了 Person(),所以現在 this 變數指向 new 創造的新的空物件的記憶體位置。

所以當我們打 .firstname.lastname 就會增加到空物件上,就像這樣。

1
2
3
4
5
6
var john = {};

john.fistname = 'John';
john.lastname = 'Doe';

console.log(john);

而在 JavaScript 中會回傳 new 運算子建立的物件,這會建立一個新物件,而成為物件的一部分也會回傳東西,所以我們試著這樣嘗試看看。

1
2
3
4
5
6
7
8
9
function Person() {
this.fistname = 'John';
this.lastname = 'Doe';
console.log('我回傳囉');
}

var john = new Person();

console.log(john);

由此可知,new 運算子會對這個函數呼叫,然後在回傳裡面的東西變成物件。

那如果 this 我們什麼都不對他做的話,他將會回傳本身。

1
2
3
4
5
6
7
8
9
10
function Person() {
console.log(this);
this.fistname = 'John';
this.lastname = 'Doe';
console.log('我回傳囉');
}

var john = new Person();

console.log(john);

但是如果我們本身若對函數回傳的話,就會變成只回傳那個資料。

1
2
3
4
5
6
7
8
9
10
11
function Person() {
console.log(this);
this.fistname = 'John';
this.lastname = 'Doe';
console.log('我回傳囉');
return { greet: '我是回傳的物件' };
}

var john = new Person();

console.log(john);

如果沒有回傳時,JavaScript 就會改找我們設定 this 的變數。

所以我們可以從這邊知道,我們可以透過函數來建構物件,而這叫做函數建構子。

那我們可以依照 函數建構子 來做一點進階的作法,假設今天 firstnamelastname 是改由我們自己傳入呢?

1
2
3
4
5
6
7
8
function Person(first, last) {
this.firstname = first;
this.lastname = last;
}

var john = new Person('John', 'Doe');

console.log(john);

所以我們可以利用函數參數的特性來傳入資料進而改變 firstnamelastname

簡單來講 new 運算子可以做出新物件,函數建構子是被用來增加新物件的屬性和方法

圖源

JavaScript 全攻略:克服 JS 奇怪的部分