最近再看jQuery源碼時,發現了一個這樣有趣的事。javascript
看下面一段代碼:java
var jquery = function () { // return new jquery.fn.init(); // return new Object(); // return 'a' // return {a:1} }; jquery.fn = jquery.prototype = { constructor: jquery }; jquery.fn.init = function () { }; jquery.fn.init.prototype = jquery.fn; var a = new jquery(); console.log(a);
輸出結果以下:jquery
這和咱們預期相符,a應該是jquery的一個實例,下面引用一段高程的原話。函數
要建立一個構造函數的新實例,必須使用new操做符。以這種方式調用構造函數實際上會經歷如下4個步驟:this
- 建立一個新對象
- 將構造函數的做用域賦給新對象(所以this就指向了這個新對象)
- 執行構造函數中的代碼(爲這個新對象添加屬性)
- 返回新對象
因此使用new操做符調用構造函數(其實函數以前並無區別,所謂構造函數也只是由於使用的是new操做符調用而已),若是構造函數沒有顯式返回值,則會返回一個構造函數的實例。那麼問題來了,若是構造函數顯示的提供了返回值呢?看下面的代碼:spa
var jquery = function () { // return new jquery.fn.init(); // return new Object(); return 'a' // return {a:1} }; jquery.fn = jquery.prototype = { constructor: jquery }; jquery.fn.init = function () { }; jquery.fn.init.prototype = jquery.fn; var a = new jquery(); console.log(a);
這裏咱們顯示的返回了一個字符串'a',可是發現a依然是jquery的一個實例prototype
再換種狀況:3d
var jquery = function () { // return new jquery.fn.init(); // return new Object(); // return 'a' return {a:1} }; jquery.fn = jquery.prototype = { constructor: jquery }; jquery.fn.init = function () { }; jquery.fn.init.prototype = jquery.fn; var a = new jquery(); console.log(a);
此次咱們返回的是一個對象,而後經過new操做符調用以後發現,a再也不是jquery的實例了,而是咱們指定的對象。code
通過反覆試驗和查閱資料,得出結論:htm
在javaScript中,若是在構造函數中顯式的返回了複雜的對象時,此時使用new操做符調用構造函數將返回構造函數中指定的對象;當構造函數中顯示返回的是相似於字符串和數字時,此時使用new操做符調用構造函數將返回構造函數的實例化對象。
這是javaScript語言的一個奇怪的特徵,但有些時候這個特徵確實有用。
好比說著名的jQuery中就用到了這個特性:
看下面這段代碼:
"use strict"; var jquery = function () { return new jquery.fn.init(); }; jquery.fn = jquery.prototype = { constructor: jquery }; jquery.fn.init = function () { }; jquery.fn.init.prototype = jquery.fn; var a = new jquery(); var b = jquery(); console.log(a); console.log(b);
咱們會發現,對於jquery這個函數,無論是用new操做符調用仍是不用new操做符調用,其返回值都是同樣的,這就得益於上面所提到了javaScript的這個古怪的特性了。
這樣一來你就不用每次使用jQuery的時候,都須要new $('#id')了,由於new $('#id')和$('#id')返回值是同樣的。
參考資料:
https://www.bennadel.com/blog/2522-providing-a-return-value-in-a-javascript-constructor.htm
http://www.w3dev.cn/article/20150912/javascript-constructor-return-value.aspx