1. 程式人生 > >jquery 原始碼解讀

jquery 原始碼解讀

jquery 原始碼大概10000多行,每行都會解析可能不是很現實,可能也只會更新一版,這都看心情。

function(global,factory){...})()

在這部分主要就是匿名函式
註釋:匿名函式的好處:自執行裡面所有東西都是區域性的,防止和程式碼衝突
那如何獲取匿名函式裡面的方法和屬性呢?
可以在裡面掛在一個物件上,比如掛在windows上面

(function (){
    function abc (){}
    window.abc = abc
})()
    abc()   
"use strict"

js的嚴禁模式;
在js嚴格模式,對js做了一些限制,主要有以下作用:
1.消除js語法不合理,不嚴謹的,減少怪異行為
2.消除程式碼執行的一些不安全之處
3.提高編譯效率,加強執行速度。
4.對未來新版本做好鋪墊。
語法的改變:
1.全域性命名必須是 v=1 其他變數var
2.禁止使用with 創設 eval作用域。
3.禁止this 指向全域性window
4.禁止內部函式遍歷呼叫棧
function f1(){
f1.caller 報錯
f1.arguments 報錯
}
5.禁止刪除變數,只有在configurable 設定為true
6.使用get方法賦值會報錯。
var o = {
get v(){return 1;}
}
o.v() =2 //報錯
7.刪除一個不可刪除的屬性, delete Object.prototype.
8.重新命名錯誤
9.引數名重複錯誤。
10.禁止八進位制
11.對arguments 引數做了限制。比如不能複製,不能追蹤引數變化,不能用callee。
12.函式宣告在頂層,不許在非函式程式碼內宣告函式
13.保留字

( typeof window !== "undefined" ? window : this, function( window, noGlobal )

這句話很清楚 判斷window 返回型別。
typeof 可以判斷 object undefined null boolean number string Symbol functuon在ECMA-262條款中實現了

var arr = [];

var document = window.document;

var getProto = Object.getPrototypeOf;

var slice = arr.slice;

var
concat = arr.concat; var push = arr.push; var indexOf = arr.indexOf; var class2type = {}; var toString = class2type.toString; var hasOwn = class2type.hasOwnProperty; var fnToString = hasOwn.toString; var ObjectFunctionString = fnToString.call( Object ); var support = {};

上面聲明瞭一些方法和一些變數。
slice 這個方法,陣列中返回選定得元素。 用法arr.slice(start,end) start -1 最後一個元素。 這個方法會返回一個新陣列。

var isFunction = function isFunction( obj ) {

      // Support: Chrome <=57, Firefox <=52
      // In some browsers, typeof returns "function" for HTML <object> elements
      // (i.e., `typeof document.createElement( "object" ) === "function"`).
      // We don't want to classify *any* DOM node as a function.
      return typeof obj === "function" && typeof obj.nodeType !== "number";
  };


var isWindow = function isWindow( obj ) {
        return obj != null && obj === obj.window;
    };




    var preservedScriptAttributes = {
        type: true,
        src: true,
        noModule: true
    };

    function DOMEval( code, doc, node ) {
        doc = doc || document;

        var i,
            script = doc.createElement( "script" );

        script.text = code;
        if ( node ) {
            for ( i in preservedScriptAttributes ) {
                if ( node[ i ] ) {
                    script[ i ] = node[ i ];
                }
            }
        }
        doc.head.appendChild( script ).parentNode.removeChild( script );
    }


function toType( obj ) {
    if ( obj == null ) {
        return obj + "";
    }

    // Support: Android <=2.3 only (functionish RegExp)
    return typeof obj === "object" || typeof obj === "function" ?
        class2type[ toString.call( obj ) ] || "object" :
        typeof obj;
}
/* global Symbol */
// Defining this global in .eslintrc.json would create a danger of using the global
// unguarded in another place, it seems safer to define global only for this module

一些程式碼,工具類吧 …

version = "3.3.1", 版本號
jQuery = function( selector, context ) {
    return new jQuery.fn.init( selector, context );
}, 
翻譯是建構函式的增強。可能是用來報錯的吧。
jQuery.fn = jQuery.prototype = {
    jquery: version,
    constructor: jQuery,
    length: 0, //在這裡看了下這個物件的長度.
    toArray: function() {
        return slice.call( this );
    }, 居然是操作DOM的方法.尷尬...
    get: function( num ) {
        if ( num == null ) {
            return slice.call( this );
        }
        return num < 0 ? this[ num + this.length ] : this[ num ];
    },
    pushStack: function( elems ) {

        // Build a new jQuery matched element set
        var ret = jQuery.merge( this.constructor(), elems );

        // Add the old object onto the stack (as a reference)
        ret.prevObject = this;

        // Return the newly-formed element set
        return ret;
    },

    // Execute a callback for every element in the matched set.
    each: function( callback ) {
        return jQuery.each( this, callback );
    },

    map: function( callback ) {
        return this.pushStack( jQuery.map( this, function( elem, i ) {
            return callback.call( elem, i, elem );
        } ) );
    },

    slice: function() {
        return this.pushStack( slice.apply( this, arguments ) );
    },

    first: function() {
        return this.eq( 0 );
    },

    last: function() {
        return this.eq( -1 );
    },

    eq: function( i ) {
        var len = this.length,
            j = +i + ( i < 0 ? len : 0 );
        return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] );
    },

    end: function() {
        return this.prevObject || this.constructor();
    },

    // For internal use only.
    // Behaves like an Array's method, not like a jQuery method.
    push: push,
    sort: arr.sort,
    splice: arr.splice
};

上面的方法都是DOM操作的。很幽默哦~ 當然當年jquery最主要的核心就是選擇器,那麼當年最輝煌的就是dom操作吧。

jQuery.extend = jQuery.fn.extend = function() {

程式碼補充,如果之前寫了 那麼將會被覆蓋~