爲什麼jquery實例化的時候不須要new 一個構造函數

如題,這個問題我曾經在支付寶的電話面試裏面最後一個問題被問到過,後來也沒有去看到底爲什麼不須要new,如今咱們就來剖析下。
並且當你在看jquery源碼的時候,若是一開始就搞不懂這樣的問題,抑或jQuery.fn.init.prototype =jQuery.fn 這樣的問題也搞不懂的話,那基本後面的東西都是懵的。jquery

首先回顧下,咱們通常是如何寫插件的,一般是這樣的面試

function Kissy () {
  
}

Kissy.prototype.alert = function () {
 
}
// 實例化必需要有,不然沒法調用原型鏈上的alert方法
var kissy = new Kissy()
kissy.alert()
// 若是咱們直接這樣調用
Kissy().alert()
// 就會報錯alert不是一個function。這裏涉及到原型繼承,new 一個構造函數和 執行普通函數的區別,不在贅述。

迴歸一個知識點,有助於咱們理解後面咱們講解的內容函數

構造函數有return值怎麼辦?
構造函數裏沒有顯式調用return時,默認是返回this對象,也就是新建立的實例對象。
當構造函數裏調用return時,分兩種狀況:
1.return的是五種簡單數據類型:String,Number,Boolean,Null,Undefined。
這種狀況下,忽視return值,依然返回this對象。
2.return的是Object
這種狀況下,再也不返回this對象,而是返回return語句的返回值。this

如何改造上面的代碼,能夠不用new函數,直接調用到alert方法呢?很簡單。改造以下:prototype

function Kissy () {
  return Kissy.prototype
}

當咱們直接調用Kissy()函數的時候,不是返回的null或undefined而是返回Kissy的原型,即返回了一個原型對象,這個對象上是有alert方法的,這就好像咱們熟悉的下面的代碼同樣插件

var obj = {
  name: 'zj',
  getName: function() {
    console.log(this.name)
  }
}
obj.getName() // zj

接下來,咱們仿造jquery源碼又來改造下:code

function Kissy () {
      return new Kissy.fn.init()
}
    
Kissy.fn = Kissy.prototype = {
  constructor: Kissy,
  init: function() {
      console.log('init')
  }
}

Kissy.fn.init.prototype = Kissy.fn

Kissy.fn.alert = function() {
    alert('0000')
}
Kissy().alert()  // 00000

無非就是在Kissy上面增長了一個fn屬性,這個屬性指向了Kissy.prototype。這樣的目的是便於咱們開發插件的時候,在原型上增長方法能夠直接這麼寫Kissy.fn.alert 僅此而已。爲什麼構造函數不直接返回
Kissy.fn呢 而是在中間搞了一個init.讀過jquery源碼的都知道,jquery.fn.init 這個函數實際是jquery的初始化函數。這裏就不在展開了。對象

return new Kissy.fn.init()

構造函數返回了一個Kissy.fn.init()這個函數的一個實例。固然就會繼承這個實例上的原型,而原型又被咱們重置了繼承

Kissy.fn.init.prototype = Kissy.fn

因此就能調用到Kissy.fn上面的alert方法了,不信你們能夠試試哦。支付寶

再來看jquery的源碼,對比剛剛分析的代碼,是否是基本如出一轍,只是jquery源碼fn.init方法有比較多初始化的內容。

jQuery = function( selector, context ) {
    return new jQuery.fn.init( selector, context, rootjQuery );
},
jQuery.fn = jQuery.prototype = { //fn即對應prototype
    constructor: jQuery,
    init: function( selector, context, rootjQuery ) {
        ...
        return this;
    }
    ...
}
jQuery.fn.init.prototype = jQuery.fn;
相關文章
相關標籤/搜索