深刻理解javascript系列(十八):掌握面向對象(1)

面向對象,一個老生常談的話題,但你有沒有想過面向對象要解決什麼問題?css

有一位大神說的很直接,」面向對象要解決的問題,並非封裝、繼承和多態,而是寫代碼的套路「。bash

我以爲有理,因此簡單粗暴點,今天略看下jQuery的封裝。函數

使用jQuery時,咱們一般會這樣寫:ui

//聲明一個JQ實例
$('.target')

//獲取元素的css屬性
$('.target').css('width')

//獲取元素的位置信息
$('.target')複製代碼

是否是與普通的對象實例不太同樣,new關鍵字去哪了,$符合又是什麼?固然咯,您確定是知道的,如今就讓咱們來簡化一下JQ吧。this

一個庫就是一個單獨的模塊,所以咱們使用自執行函數的方式模擬一個模塊。spa

(function() {
    // to do something
})()複製代碼

既然可以在全局直接調用jQuery,則說明JQ被掛載在了全局對象上。所以當咱們在模塊中對外提供接口時,能夠採起window.jQuery的方式。prototype

var jQuery = function() {};

//....

window.jQuery = jQuery複製代碼

咱們在使用過程當中,並無使用jQuery,而是使用了$,其實只是多加了一個賦值操做。code

window.$ = window.jQuery = jQuery複製代碼

在使用過程當中直接使用$,其實至關於直接調用構造函數jQuery建立了一個實例,而沒有使用new。可是建立一個實例時,new關鍵字是必不可少的,由此說明new的操做被放在了jQuery方法中來實現了,而jQuery並非真正的構造函數,對象

咱們應該知道,函數能夠扮演很多角色,對象啊,類啊...JQ內部的實現其實就是利用這個,在具體實現時,改變內部某些函數的prototype指向。下面咱們就來看看實現代碼把。繼承

(function(ROOT) {
    
    //構造函數
    var jQuery = function(selector) {
        //在該方法中直接返回new建立的實例,
        //所以這裏的init纔是真正的構造函數

        return new jQuery.fn.init(selector);
    }

    jQuery.fn = jQuery.prototype = {
        constructor: jQuery,
        version:'xxx',
        init: function(selector) {
            var elem, selector;
            elem = document.querySelector(selector);
            this[0] = elem;

            return this;
        },
             //在原型上添加一堆方法     ...
    }

    //讓init方法的原型指向jQuery的原型
    jQuery.fn.init.prototype = jQuery.fn;
    
    ROOT.jQuery = ROOT.$ = jQuery;

})(window)複製代碼

在上面的實現中,首先在jQuery構造函數中聲明瞭一個fn屬性,並將其指向了jQuery的原型。隨後在原型對象上添加了init方法。

jQuery.fn = jQuery.prototype = {
    init: function() {}
}複製代碼

以後又將init的原型指向了jQuery.prototype.

jQuery.fn.init.prototype = jQuery.fn;複製代碼

而在構造函數jQuery中,則返回了init的實例對象。

var jQuery = function(selector) {
        return new jQuery.fn.init(selector);
    }複製代碼

最後對外暴露接口時,將字符串$與方法jQuery對等起來。

ROOT.jQuery = ROOT.$ = jQuery;

複製代碼

所以當使用$('xxxx')建立一個jQuery實例時,實際上調用的是jQuery('xxxx')建立的一個init實例。這裏正是構造函數原型上的init方法。

其實,到這裏我是有不少疑問的。

一、你知道爲何要爲自執行函數設置參數window嗎?

二、你知道爲何要在構造函數jQuery內部用new建立並返回另外一個構造函數的實例嗎?

三、你知道爲何要jQuery.fn = jQuery.prototype,設置jQuery.fn 指向構造函數jQuery()的原型對象jQuery.prototype嗎?

四、你知道爲何能在構造函數jQuery.fn.init()的實例上調用構造函數jQuery()的原型方法和屬性嗎?

....

相關文章
相關標籤/搜索