jQuery源码笔记——三

将类数组对象转化为数组对象

javascript中有许多类数组对象,比如HTMLCollection,NodeList,arguments。她们的特点是和数组一样有length属性,并且有0,1,2这样的位置属性。在代码编写中我们经常需要将他们转化为数组对象。

//mini类数组对象
var arrayLike = {
    0: "a",
    1: "b",
    2: "c",
    length: 3
}
console.log(Array.prototype.slice.call(arrayLike))

我们来详细分析一下Array.prototype.slice.call(arrayLike)。数组的中有slice方法,存放在数组的原型中也就是Array.prototype.slice,它操作的返回值是一个数组;call具有修改上下文的作用,本例就是将slice的上下文改为arrayLike。所以这句话就实现了将类数组对象转化为数组对象的功能。

.get()实现

var jQuery = function( selector, context ) {
        return new jQuery.fn.init( selector, context );
};
jQuery.fn = jQuery.prototype = {
    init: function(selector){
        this.selector = selector;
        //从IE8之后提供了querySelectorAll,我们先利用它mini化选择器
        //返回的是伪数组对象NodeList
        var result = document.querySelectorAll(selector);
        //将NodeList转化为jQuery对象。
        for(var i = 0;i < result.length;i++){
            this[i] = result[i] 
        }
        //模拟jQuery对象的length属性
        this.length = result.length;
    }
}
jQuery.fn.init.prototype = jQuery.fn
//不利用extend ,直接向原型里添加属性方法get
jQuery.fn.get = function(index) {
        return index != null ? (index < 0 ? this[this.length + index]:this[index]):Array.prototype.slice.call(this);
}
//测试
console.log(jQuery("div").get(0))

.get的作用是转化为DOM节点,或者是DOM节点数组。注意一些特别的情况。

.eq()实现

var jQuery = function( selector, context ) {
        return new jQuery.fn.init( selector, context );
};
jQuery.fn = jQuery.prototype = {
    selector: "",
    init: function(selector){
        //仍然是mini的选择器。
        var result = document.querySelectorAll(selector);
        for(var i = 0;i < result.length;i++){
            this[i] = result[i] 
        }
        this.length = result.length;
    },
    pushStack: function( elems ) {
        //将空jQuery对象和elems合并
        var ret = jQuery.merge( this.constructor(), elems );
        //设置前一个对象,作回来的索引。
        ret.prevObject = this;

        // 新形成jQuery的对象
        return ret;
    },
    eq : function( i ) {
        //将负数位置转化为正数位置
        var j = + i + ( i < 0 ? this.length:0);
        //在范围内返回指定对象包成的数组,否则返回空数组
        return this.pushStack((j >= 0&& j<this.length)?[this[j]]:[])
    },
    //将原型的构造函数设置为jQuery,可以用jQuery.constructor创造新的空对象;相关语句this.constructor;jQuery.prototype;
    constructor : jQuery
}
jQuery.fn.init.prototype = jQuery.fn
//将两个类数组对象或数组对象合并,并设置,length
jQuery.merge = function( first, second ) {
        var len = +second.length,
            j = 0,
            i = first.length;
        for ( ; j < len; j++ ) {
            first[ i++ ] = second[ j ];
        }

        first.length = i;

        return first;
};
//测试
console.log(jQuery("div").eq(0))

先讲两个相关函数jQuery.fn.pushStatic和jQuery.merge。

写在jQuery.fn里的函数实际写在原型里,用到这个原型的构造函数都会继承;而写在jQuery里的实际是在一个独立的jQuery对象,只能通过jQuery.[函数名]的形式引用。

merge实际的功能是合并两个数组或者类数组对象,放到第一个对象中,并设置他们合并后的长度。pushStatic调用了merge,第一个参数为jQuery空对象(this.constructor()),将第二个数组或者类数组合并到jQuery空对象中,形成新的jQuery对象,并返回。

eq的功能就是get的功能多一个转化成jQuery对象,调用pushStatic,并返回其返回值一个新的jQuery对象。

first和last和end

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

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

    end: function() {
        return this.prevObject || this.constructor(null);
    },
posted on 2014-11-06 20:19  吹过的风  阅读(141)  评论(0编辑  收藏  举报