摘要:關于操作符,我的理解一里有進一步描述舉例即是構造函數在本例中,對象具有特定的類型,可稱之為一個對象。用作對象類型的標記使用構造函數創建的對象可以很方便的檢查它們的類型,比如為對象創建共享屬性這可能是使用構造函數最重要的理由了。
JavaScript 中的構造器 什么是構造器?
構造器也叫構造函數,它就是一個普通的函數,只不過它的主要目的是用于和 new 操作符配合來創建特定類型的對象。(關于 new 操作符,我的理解 JavaScript(一)里有進一步描述)
舉例:
var me = new Person("Albert", "Yu", 32); // Person 即是構造函數
在本例中,me 對象具有特定的類型,可稱之為:一個 Person 對象。而 Person 就是它的類型名字。
那么構造函數內部又是如何工作的?
function Person(firstName, lastName, age) { this.firstName = firstName; this.lastName = lastName; this.age = age; };
和普通的函數相比,有兩個明顯的區別,解釋如下:
函數名稱首字母大寫:這其實只是一個約定而不是強制行為,絕大多數 JavaScript 程序員都會遵守這個約定,即首字母大寫的函數名是一個構造函數;當然,首字母小寫的函數一樣可以充當構造函數
使用 this 捆綁局部變量:一般性的函數都是直接創建本地變量來保存值,而構造函數使用 this 捆綁局部變量是為了配合 new 操作符。因為 new 操作符會創建一個新對象,并且把新對象綁定在構造函數內部的 this 上,于是被捆綁在 this 上的局部變量事實上就成為新對象的屬性了
因此,這樣的構造函數所創建的對象大致等價于:
var me = { firstName: "Albert", lastName: "Yu", age: 32 };
那么既然如此,我們為啥還要寫構造函數?
構造函數的用處 1. 用作創建對象的模板如果只需要創建少量對象(比如一個),編寫構造函數的確沒太大意義。但是遇到需要重復創建對象的場合,構造函數顯然是 DRY(Don"t Repeat Youself)的上佳選擇。
不僅僅是為了減少重復編碼的工作量,而且經常會有對于輸入參數進行驗證并拋出錯誤的功能設計,也可以借助構造函數來完成。
2. 用作對象類型的標記使用構造函數創建的對象可以很方便的檢查它們的類型,比如:
var me = new Person("Albert", "Yu", 32); var you = { firstName: "Super", lastName: "Man", age: 18 }; console.log(me instanceof Person); // true console.log(you instanceof Person); // false3. 為對象創建共享屬性
這可能是使用構造函數最重要的理由了。基于原型繼承的 JavaScript 可以很方便的為對象擴充成員屬性:
var me = new Person("Albert", "Yu", 32); me.firstName; // "Albert" me.lastName; // "Yu" me.age; // 32 // 我想要標記所有的 Person 對象都是活著的…… Person.prototype.isAlive = true; me.isAlive; // true // 我還想要輸出用戶的全名…… me.firstName + " " + me.lastName; // "Albert Yu" // 這樣太二了吧? Person.prototype.fullName = function() { return [this.firstName, this.lastName].join(" "); }; me.fullName(); // "Albert Yu" // 嗯,文藝多了……
有一點特別需要注意的!
使用構造函數創建對象一定要使用 new 操作符
這是因為(再次強調):真正創建新對象的不是構造函數,而是 new 操作符。構造函數只是充當新對象的模板,它接收 new 創建的對象然后用模板填充這個對象的屬性設置。
鑒于此,忘記使用 new 的話是比較危險的。因為沒有 new 創建新對象的時候,構造函數內的 this 會被捆綁給全局對象,通常是 window(瀏覽器)或者 global(Node.js),讓我們看看會發生啥事兒吧……
var me = new Person("Albert", "Yu", 32); me.firstName; // "Albert" var you = Person("Super", "Man", 18); you.firstName; // undefined... WTF?! this.firstName; // "Super"...Shiiiit! // 上面的 this 是全局對象
那么如何改進構造函數呢?簡單。
function Person(firstName, lastName, age) { if (this instanceof Person) { // 想一想還有沒有其他的判斷方式? this.firstName = firstName; this.lastName = lastName; this.age = age; } else { throw new Error("不用 `new` 是不可以的喲~~~"); } }
這個思路就是先判斷構造函數接收到的 this 是不是自己的實例,若是則一切好說,若不是則拋出錯誤強制用戶使用 new 操作符。
當然,這個改進雖然可靠了,但還是不夠“聰明”,要是能讓構造函數自己判斷來自動使用 new 該多好呀!沒錯,這是更好地方式,不過在這里我就不演示了,還是由您自己來動手實踐一下吧?(提示:考慮一下構造函數的原型對象。如果想不出來的話不要緊,我們以后接著聊)
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/77965.html
摘要:第四點也要著重講下,記住構造函數被操作,要讓正常作用最好不能在構造函數里 4) this、new、call和apply的相關問題 講解this指針的原理是個很復雜的問題,如果我們從javascript里this的實現機制來說明this,很多朋友可能會越來越糊涂,因此本篇打算換一個思路從應用的角度來講解this指針,從這個角度理解this指針更加有現實意義。 下面我們看看在ja...
摘要:是詞法作用域工作模式。使用可以將變量綁定在所在的任意作用域中通常是內部,也就是說為其聲明的變量隱式的劫持了所在的塊級作用域。 作用域與閉包 如何用js創建10個button標簽,點擊每個按鈕時打印按鈕對應的序號? 看到上述問題,如果你能看出來這個問題實質上是考對作用域的理解,那么恭喜你,這篇文章你可以不用看了,說明你對作用域已經理解的很透徹了,但是如果你看不出來這是一道考作用域的題目,...
摘要:是詞法作用域工作模式。使用可以將變量綁定在所在的任意作用域中通常是內部,也就是說為其聲明的變量隱式的劫持了所在的塊級作用域。 作用域與閉包 如何用js創建10個button標簽,點擊每個按鈕時打印按鈕對應的序號? 看到上述問題,如果你能看出來這個問題實質上是考對作用域的理解,那么恭喜你,這篇文章你可以不用看了,說明你對作用域已經理解的很透徹了,但是如果你看不出來這是一道考作用域的題目,...
摘要:是詞法作用域工作模式。使用可以將變量綁定在所在的任意作用域中通常是內部,也就是說為其聲明的變量隱式的劫持了所在的塊級作用域。 作用域與閉包 如何用js創建10個button標簽,點擊每個按鈕時打印按鈕對應的序號? 看到上述問題,如果你能看出來這個問題實質上是考對作用域的理解,那么恭喜你,這篇文章你可以不用看了,說明你對作用域已經理解的很透徹了,但是如果你看不出來這是一道考作用域的題目,...
閱讀 903·2021-11-22 13:53
閱讀 2533·2021-10-15 09:40
閱讀 1001·2021-10-14 09:42
閱讀 3475·2021-09-22 15:59
閱讀 888·2021-09-02 09:47
閱讀 2368·2019-08-30 15:54
閱讀 1438·2019-08-29 17:14
閱讀 400·2019-08-29 15:15