對建構子有很好的理解是你掌握JavaScript這門語言的重點。 我們都知道JavaScript不像其他語言,它沒有class
關鍵字,但是它有跟function
非常相似的建構子。這篇文章我們一起來詳細了解JavaScript建構子如何建構物件。
建構子跟普通函數非常相似,但是我們透過new
關鍵字來使用它們。主要有兩種類型的建構函數,native
建構子(Array
,Object
)它們可以在執行環境中自動生成,還有自訂的建構函數,你可以定義自己的方法和屬性。
當你想要建立很多相似的物件(擁有相同的屬性和方法)的時候,使用建構函式是非常有效的。大部分程式設計師都遵循公約,使用大寫字母開頭來將建構函數和普通函數區分開。看看下面的程式碼。
function Book() { // unfinished code} var myBook = new Book();
最後一行程式碼創建了一個Book
對象,並把它賦值給變數;這樣完成之後,即使Book
建構器沒有做任何操作,myBook
也是Book
實例。正如你所看到的,除了首字母大寫和使用new
關鍵字之外,建構函數和普通函數並沒有什麼區別。
判斷某個物件是否為某種實例,我們可以使用instanceof
運算子:
myBook instanceof Book // => truemyBook instanceof String // => false
注意:如果右邊不是函數的實例,那麼將會報錯:
myBook instanceof {}; // => TypeError: invalid 'instanceof' operand ({})
另一種方法是使用constructor
屬性,所有物件實例都有一個constructor
屬性,這個屬性指向建立它的建構子。
myBook.constructor == Book; // => true
就像myBook
的constructor
指向Book
一樣。 所有物件都從它們的原型上繼承了constructor
這個屬性:
var s = new String("text"); s.constructor === String; // => true"text".constructor === String; // => truevar o = new Object(); o.constructor === Object; // => truevar o = {}; o.constructor === Object; // => truevar a = new Array(); a.constructor === Array; // => true[].constructor === Array; // => true
儘管使用constructor
可以用來偵測實例類型,但是建議還是使用 instanceof
方法。因為constructor
屬性是可以被重寫的..用起來不太可靠。
建構子就像餅乾印模。同一印模製作出來的,都是同一個diao樣(男人沒一個好東西也是這個道理)。
function Book(name, year) { this.name = name; this.year = '(' + year + ')'; }
Book
建構器需要兩個參數,當使用new
關鍵字建構物件時,會把兩個形參傳給Book
物件的name
和year
。
var firstBook = new Book("Pro AngularJS", 2014);var secondBook = new Book("Secrets Of The JavaScript Ninja", 2013); var thirdBook = new Book("JavaScript Patterns", 2010); console.log(firstBook.name, firstBook.year); console.log(secondBook.name, secondBook.year); console.log(thirdBook.name, thirdBook.year);
如你所見,我們可以透過傳不同參數,快速建立另一本書。 JavaScript的Array()
,Date()
也是這個道理。
Object.defineProperty
方法可以在建構器中被用來配置屬性。
function Book(name) { Object.defineProperty(this, "name", { get: function() { return "Book: " + name; }, set: function(newName) { name = newName; }, configurable: false }); }var myBook = new Book("Single Page Web Applications"); console.log(myBook.name); // => Book: Single Page Web Applications// we cannot delete the name property because "configurable" is set to falsedelete myBook.name; console.log(myBook.name); // => Book: Single Page Web Applications// but we can change the value of the name propertymyBook.name = "Testable JavaScript"; console.log(myBook.name); // => Book: Testable JavaScript
上面的程式碼中是呼叫了祖先的方法。它提供了getter
和setter
介面。 getter
方法負責傳回封裝的值,setter
方法接受參數,並且把值賦給屬性。當我們在某個屬性上操作訪問時,呼叫的就是這兩個方法。透過設定configurable
,我們可以設定該值能否被刪除。
JavaScript語言九種內建的建構子:Object()
, Array()
, String()
, Number()
, Boolean()
, Date()
, Function()
, Error()
以及RegExp()
。當我們需要建立這些值的時候,我們可以自由選擇使用字面量或建構器。但是在相同情況下,字面量物件不僅易讀,而且運行速度更快,因為他們可以在解析的時候被最佳化。所以當你需要使用簡單物件的時候就使用字面量吧。
// a number object// numbers have a toFixed() methodvar obj = new Object(5); obj.toFixed(2); // => 5.00// we can achieve the same result using literalsvar num = 5; num.toFixed(2); // => 5.00// a string object// strings have a slice() method var obj = new String("text"); obj.slice(0,2); // => "te"// same as abovevar string = "text";string.slice(0,2); // => "te"
記得使用建構器的時候要用new
關鍵字,如果你不小心忘記了,那麼建構器中的this
指向的是global
物件(瀏覽器中預設為window
)。
function Book(name, year) { console.log(this); this.name = name; this.year = year; }var myBook = Book("js book", 2014); console.log(myBook instanceof Book); console.log(window.name, window.year);var myBook = new Book("js book", 2014); console.log(myBook instanceof Book); console.log(myBook.name, myBook.year);
上面的程式碼運行結果如下所示:
#如果是在嚴格模式下,上面的程式碼將會拋出錯誤,因為嚴格模式不允許我們不使用new
關鍵字呼叫建構器。
為了解決可能會忘記使用new
關鍵字的風險,我們可以透過判斷this
的值建立適用範圍更高的構造器。
function Book(name) { if (!(this instanceof Book)) { // the constructor was called without "new". return new Book(name); } }
加上這段程式碼之後,我們就可以『肆無忌憚』地使用建構器了。
function Book(name, year) { if (!(this instanceof Book)) { return new Book(name, year); } this.name = name; this.year = year; }var person1 = new Book("js book", 2014);var person2 = Book("js book", 2014); console.log(person1 instanceof Book); // => trueconsole.log(person2 instanceof Book); // => true
很多内建的构造器都是这么做的。通过判断this
是否为当前类型。如果程序员忘记加new
关键字,那么我们就返回一个通过new
出来的对象。
JavaScript没有类这种说法(但是它可以使面向对象的),所以对于习惯了使用类的程序员来说是种困惑。当然JavaScript的构造函数跟普通函数没什么区别,只是通过new
关键字生成出来而已。如果我们需要”印饼干”的话,它就非常有用了。
相关推荐:
以上是JavaScript構造器詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!