首頁 > web前端 > js教程 > 主體

深入了解JavaScript中的構造器

青灯夜游
發布: 2020-10-13 17:50:32
轉載
1805 人瀏覽過

深入了解JavaScript中的構造器

對建構子有很好的理解是你掌握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    // => true
myBook 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; // => true
var o = new Object();
o.constructor === Object;      // => true
var o = {};
o.constructor === Object;      // => true
var 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中的構造器

如你所見,我們可以透過傳不同參數,快速建立另一本書。 JavaScript的Array(),Date()也是這個道理。

Object.defineProperty 方法

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 false
delete myBook.name;    
console.log(myBook.name);    // => Book: Single Page Web Applications
// but we can change the value of the name property
myBook.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() method
var obj = new Object(5);
obj.toFixed(2);     // => 5.00
// we can achieve the same result using literals
var 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 above
var string = "text";
string.slice(0,2);  // => "te"
登入後複製

使用new關鍵字是必不可少的

記得使用建構器的時候要用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);
登入後複製

上面的程式碼運行結果如下所示:

深入了解JavaScript中的構造器

#如果是在嚴格模式下,上面的程式碼將會拋出錯誤,因為嚴格模式不允許我們不使用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);    // => true
console.log(person2 instanceof Book);    // => true
登入後複製

很多內建的建構器都是這麼做的。透過判斷this是否為目前類型。如果程式設計師忘記加上new關鍵字,那麼我們就回傳一個透過new出來的物件。

結論

JavaScript沒有類別這種說法(但是它可以使物件導向的),所以對於習慣了使用類別的程式設計師來說是種困惑。當然JavaScript的建構子跟普通函數沒什麼差別,只是透過new關鍵字產生出來而已。如果我們需要」印餅乾」的話,它就非常有用了。

更多程式相關知識,請造訪:程式設計入門! !

以上是深入了解JavaScript中的構造器的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:w3cplus.com
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板