zepto.js源码解读(三):zepto.Z函数

在了解zepto.Z函数之前,有必要了解一下原型链,继承等方面的知识。推荐阅读下以下博客:深入理解JavaScript原型和闭包

每个函数都有一个prototype(原型),这个函数的原型的constructor属性指向它自己。通过new操作符出来的实例都有一个__proto__(我们可以称之为隐式原型),指向创建它的函数的prototype(原型)。

下面是成立的:

var obj = new Function();
obj.prototype.constructor === obj;   //true
obj.__proto__ === Function.prototype  // true

查找obj的属性时,会先从自身去查找,如果有就返回该属性,然后结束查找。如果没有就沿着obj的原型链查找,有则返回。所有通过new操作符生成的实例函数都能继承来自obj.__proto__中的属性。

可对比以下两段代码:

var obj = new Function();
obj.__proto__ === Function.prototype  // true
obj.info  // undefined
obj.info = "李厚春";
obj.info  // "李厚春"
obj.__proto__.info = "前端攻城狮";
obj.info //"李厚春"
var obj= new Function();
obj.__proto__ === Function.prototype  // true
obj.info  // undefined
obj.__proto__.info = "前端攻城狮";
obj.info //"前端攻城狮"

这样就实现了继承:obj本身没有info属性,它继承了来自obj.__proto__中的属性。

zepto.Z()函数在源码(指的是带注释的zepto.js)172行中是这样定义的:

zepto.Z = function(dom, selector) {
    return new Z(dom, selector)
  }

它返回了一个由Z()函数通过new操作符生成的构造函数。

即:

zepto.Z.__proto__ === Z.prototype

源码408行:

$.fn = {
    constructor: zepto.Z,
    //....
}

指定了$.fn的constructor属性值:zepto.Z。

即:

$.fn.constructor = zepto.Z

结合源码的938行(zepto.Z.prototype = Z.prototype = $.fn):

//拆开看
 zepto.Z.prototype = $.fn

把zepto.Z的原型指定为:$.fn。

即:

zepto.Z.prototype.constructor === zepto.Z

(这就实现了zepto.Z的原型的constructor属性指向它自己: zepto.Z)。

下面代码:


  Z.prototype = $.fn

Z.prototype = $.fn 把Z的原型修改为 $.fn

因为zepto.Z是由Z通过new操作符生成的实例。

(这里就实现了zepto.Z的隐式原型(__proto__)就指向创建它的函数的原型(Z.prototype),即指向了 $.fn。

即:

zepto.Z.__proto__ = == $.fn。

红字部分的逻辑就保证了zepto.Z符合JavaScript原型和继承关系的逻辑。

由上: zepto.Z就继承了$.fn的属性和方法。

源码的408-849行定义了$.fn的属性和方法。

回头缕一下思路:

var Zepto = (function(){
    var $,
        zepto = {};

        function Z(dom, selector) {
            var i, len = dom ? dom.length : 0
            for (i = 0; i < len; i++) this[i] = dom[i]
            this.length = len
            this.selector = selector || ''
        }

    // ...

   zepto.Z = function(dom, selector) {
    return new Z(dom, selector)
  }

    zepto.init = function(selector, context) {
        var dom
        //分情况对dom赋值,
        //并返回zepto.Z的值
        return zepto.Z(dom, selector)
    }

    $ = function(selector, context){
        return zepto.init(selector, context)
    }

    $.fn = {
        constructor: zepto.Z,
        // $.fn的属性和方法
    }

    //...
    zepto.Z.prototype = Z.prototype = $.fn

    return $
})()

window.Zepto = Zepto
window.$ === undefined && (window.$ = Zepto)

我们在用$(‘div’)初始化一个zepto对象的时候:

这里写图片描述


为了保持思维的连贯性,上面没有说到Z这个函数:

function Z(dom, selector) {
    var i, len = dom ? dom.length : 0
    for (i = 0; i < len; i++) this[i] = dom[i]
    this.length = len
    this.selector = selector || ''
  }

可以看到 通过传入 dom和selector,生成了一个类数组对象: Z。

这样它的实例对象(zepto.Z)也是一个类数组对象,zepto.Z的length属性就是传入dom的length属性,zepto.Z的selector就是传入的selector。

猜你喜欢

转载自blog.csdn.net/lihchweb/article/details/78134826
今日推荐