首頁  >  文章  >  web前端  >  有關js框架的原始碼研究

有關js框架的原始碼研究

巴扎黑
巴扎黑原創
2017-08-10 13:21:301455瀏覽

[導讀] underscore js原始碼Underscore js 沒有對原生 JavaScript 物件進行擴充,而是透過呼叫 _() 方法進行封裝,一旦封裝完成,原生 JavaScript 物件就會成為 Underscore 物件。判斷給定變數是否是物件  Is

underscore.js原始碼

#Underscore.js 沒有對原生JavaScript 物件進行擴充,而是透過呼叫_() 方法來封裝,一旦封裝完成,原生JavaScript 物件就會成為一個Underscore 物件。

判斷給定變數是否是物件

// Is a given variable an object?
    _.isObject = function(obj) {        var type = typeof obj;        return type === 'function' || type === 'object' && !!obj;
    };

這是underscore.js的判斷給定變數是否是object的一段原始碼。 我們知道typeof會傳回以下六個值:

1. 'undefined' --- 这个值未定义;2. 'boolean'    --- 这个值是布尔值;3. 'string'        --- 这个值是字符串;4. 'number'     --- 这个值是数值;5. 'object'       --- 这个值是对象或null;6. 'function'    --- 这个值是函数。

&&的優先權要高與||!!的作用相當於Boolean(),將其轉換為布林值。

判斷給定值是否為DOM元素

// Is a given value a DOM element?
    _.isElement = function(obj) {        return !!(obj && obj.nodeType === 1);
    };

同樣!!相當於Boolean()的作用,nodeType == = 1則說明是元素節點,屬性attr是2 ,文字text是3

<body>
    <p id="test">测试</p><script>
    var t = document.getElementById(&#39;test&#39;);
    alert(t.nodeType);//1
    alert(t.nodeName);//p
    alert(t.nodeValue);//null</script></body>

firstChild屬性

var t = document.getElementById(&#39;test&#39;).firstChild;
alert(t.nodeType);//3alert(t.nodeName);//#testalert(t.nodeValue);//测试

文字節點也算是節點,所以p的子節點是文字節點,所以回傳3

zepto原始碼

判斷是否是陣列

isArray = Array.isArray ||            function(object){ return object instanceof Array }

#Array.isArray() 方法:如果一個物件是數組就回傳true,如果不是則回傳false

instanceof 用來判斷變數是否某個物件的實例,如

var a= [];
alert(a instanceof Array);//返回 true

同時alert(a instanceof Object) 也會回傳true

isArray 傳回布林值,如果Array.isArraytrue,則傳回true,否則傳回object instanceof Array的結果。

資料類型判斷

class2type = {},function type(obj) {        return obj == null ? String(obj) :
        class2type[toString.call(obj)] || "object"
    }    function isFunction(value) { return type(value) == "function" }    function isWindow(obj)     { return obj != null && obj == obj.window }    function isDocument(obj)   { return obj != null && obj.nodeType == obj.DOCUMENT_NODE }    function isObject(obj)     { return type(obj) == "object" }

class2type是一個空對象,實際上一個什麼都沒有的空對像是這樣建立的Object.create(null) ;

我們可以透過Object.prototype.toString.call()方法來判斷資料類型,例如:

console.log(Object.prototype.toString.call(123)) //[object Number]  console.log(Object.prototype.toString.call(&#39;123&#39;)) //[object String]    console.log(Object.prototype.toString.call(undefined)) //[object Undefined]                         console.log(Object.prototype.toString.call(true)) //[object Boolean]                                      console.log(Object.prototype.toString.call({})) //[object Object]                                      console.log(Object.prototype.toString.call([])) //[object Array]             console.log(Object.prototype.toString.call(function(){})) //[object Function]

首先如果參數obj undefinednull,則透過String(obj)轉換為對應的原始字串“undefined”或“ null」。

然後class2type[toString.call(obj)]先借用Object的原型方法toString()來取得obj的字串表示,傳回值的形式是[object class],其中的class是內部物件類別。

然後從物件class2type中取出[object class]對應的小寫字串並傳回;如果未取到則一律傳回「object。 +length

,

length

為集合的長度.

可能你剛剛看到slice.call(this)會覺得很納悶,其實不只zepto.js的原始碼,包括jQuerybackbone

的原始碼都是這麼寫的,只不過它們在最開頭做了聲明:

get: function(idx){            return idx === undefined ? slice.call(this) : this[idx >= 0 ? idx : idx + this.length]
        },
所以slice.call(this)其實還是Array.slce.call(this)prototype.js原始碼
var push = array.push;var slice = array.slice;var splice = array.splice;

因為

addClassName依賴removeClassName(),所以先分析後者,$()

是先將元素封裝成

prototype

對象,

  //为对象添加 class 属性值

   addClassName: function(element, className) {
        element = $(element);
        Element.removeClassName(element, className);
        element.className += &#39; &#39; + className;
    },   //为对象移除 class 属性值

    removeClassName: function(element, className) {
        element = $(element);        if (!element)            return;        var newClassName = &#39;&#39;;        var a = element.className.split(&#39; &#39;);        for (var i = 0; i < a.length; i++) {            if (a[i] != className) {                if (i > 0)
                    newClassName += &#39; &#39;;
                newClassName += a[i];
            }
        }
        element.className = newClassName;
    },
這句話的意思是如果元素物件不存在,則忽略不再繼續執行的意思,也就是終止的意思。 ##) 用作分隔符,那麼該物件中的每個字元之間都會被分割。方法
if(!element)  return
!Array.prototype.push如果為true,表示瀏覽器不支援該方法,則往下執行。 i] = arguments[i]將傳遞進來的每個參數依序放入陣列中,最後傳回陣列的長度

存取物件可以使用

(.)

表示法,也可以使用[]來訪問,同樣訪問數組元素也是

jQuery 源碼

jQuery

源碼太多關聯了,所以不好單獨拿出來做分析,就舉一兩個簡單的例子:toArray方法<pre class="hljs perl">split() 方法用于把一个字符串分割成字符串数组。</pre>Array.prototype.slice.call(arguments)能將具有

length

屬性的物件轉成數組,也就是說其目的是將arguments物件的陣列提出來轉換為數組。例如:<pre class="hljs javascript">//是否拥有 class 属性值hasClassName: function(element, className) { element = $(element); if (!element) return; var a = element.className.split(&amp;#39; &amp;#39;); for (var i = 0; i &lt; a.length; i++) { if (a[i] == className) return true;//返回正确的处理结果 } return false;//返回错误的处理结果},</pre>

Array

這是我們想要的基底物件名稱

prototype

這可以被認為是一個數組的實例方法的命名空間

slice
这提取数组的一部分并返回新的数组,并没有开始和结束索引,它只是返回一个数组的拷贝

call
这是一个非常有用的功能,它允许你从一个对象调用一个函数并且使用它在另一个上下文环境

下面的写法是等效的:

Array.prototype.slice.call == [].slice.call

看这个例子:

object1 = {
    name:&#39;frank&#39;,
    greet:function(){
        alert(&#39;hello &#39;+this.name)
    }
};

object2 = {
    name:&#39;trigkit4&#39;};// object2没有greet方法// 但我们可以从object1中借来

 object1.greet.call(object2);//弹出hello trigkit4

分解一下就是object1.greet运行弹出hello + 'this.name',然后object2对象冒充,this就指代object2

var t = function(){    console.log(this);// String [ "t", "r", "i", "g", "k", "i", "t", "4" ]    console.log(typeof this);  //  Object    console.log(this instanceof String);  // true};
t.call(&#39;trigkit4&#39;);

call(this)指向了所传进去的对象。

Object.prototype中已经包含了一些方法:

    1.toString ( )

    2.toLocaleString ( )

    3.valueOf ( )

    4.hasOwnProperty (V)

    5.isPrototypeOf (V)

    6.propertyIsEnumerable (V)

on方法

jQuery.fn.extend({
    on: function( types, selector, data, fn, /*INTERNAL*/ one ) {        var type, origFn;        // Types can be a map of types/handlers
        if ( typeof types === "object" ) {            // ( types-Object, selector, data )
            if ( typeof selector !== "string" ) {                // ( types-Object, data )
                data = data || selector;
                selector = undefined;

            }
        }
})


jQuery.extend(object) :为扩展jQuery类本身.为类添加新的方法。

jQuery.fn.extend(object) :给jQuery对象添加方法。

!= 在表达式两边的数据类型不一致时,会隐式转换为相同数据类型,然后对值进行比较.
!== 不会进行类型转换,在比较时除了对值进行比较以外,还比较两边的数据类型, 它是恒等运算符===的非形式。

on : function(){}js对象字面量的写法

{键:值,键:值}语法中的“健/值”会成为对象的静态成员。如果给某个“健”指定的值是一个匿名函数,那么该函数就会变成对象的静态方法;否则就是对象的一个静态属性。
有關js框架的原始碼研究

jQuery类型判断

type: function( obj ) {            if ( obj == null ) {                return obj + "";
            }            return typeof obj === "object" || typeof obj === "function" ?
            class2type[ toString.call(obj) ] || "object" :                typeof obj;
        },

前面已经分析了,class2type = {};所以class2type[ toString.call(obj) ] =
{}.toString.call(obj)。它的作用是改变toStringthis指向为object的实例。

以上是有關js框架的原始碼研究的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn