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);

    },

你可能感兴趣的:(jquery)