因为时间关系:本次仅仅对这三个API($.camelCase、$.contains、$.each)方法进行分析

第一个方法变量转驼峰:$.camelCase('hello-world-welcome');
源代码:
var camelize;
/**
 * 字符串替换
 * 使用replace第二个參数带回调
 */
camelize = function(str) {
     return str.replace(/-+(.)?/g,
          function(match, chr) {
               return chr ? chr.toUpperCase() : '';
          }
     );

};
/**
 * 将一组字符串变成驼峰命名法
 */
$.camelCase = camelize;

第二个方法检查父节点是否包括给定的dom节点,假设两者是同样节点,返回false:$.contains(parent, node)
源代码:
/**

 * $.contains(parent, node);

 * 检查父节点是否包括给定的dom节点,假设两者是同样节点,返回false

 * return {boolean} true/false

 */
$.contains = document.documentElement.contains ?

     function (parent, node) {
          return parent !== node && parent.contains(node);
     } :
     function (parent, node) {
          while (node && (node = node.parentNode)) {
               if (node === parent) {
                    return true;
               }
          }
          return false;  
     };

第三个方法遍历数组或以key-value值对方式遍历对象。回调函数返回false时停止遍历。
$.each(collection, function(index, item) { ... }) => collection
遍历数组元素或以key-value值对方式遍历对象。

回调函数返回false时停止遍历。

$.each(['a', 'b', 'c'], function(index, item) {
     console.log('item %d is: %s', index, item);
});
var hash = { name: 'zepto.js', size: 'micro' };
$.each(hash, function(key, value) {
     console.log('%s: %s', key, value);
});

源代码:
/**
 * Zepto对象迭代器
 * @param {object|array} elements 数据对象
 * @param {function} callback 回调函数
 * return {object|array} elements 数据对象
 */
$.each = function(elements, callback) {
     var i;
     var key;
     // 数组检測
     if (likeArray(elements)) {
          for (i = 0; i < elements.length; i++) {
               if (callback.call(elements[i], i, elements[i]) === false) {
                    return elements;
               }
          }
     } else {
          for (key in elements) {
               if (callback.call(elements[key], key, elements[key]) === false) {
                    return elements;
               }
          }
     }
     return elements;
};

三个方法最后页面:demo.html
<!DOCTYPE html>

<html>

    <head>

        <meta http-equiv="X-UA-Compatible" content="IE=Edge" />

        <meta charset="utf-8" />

        <title>Zepto源代码分析</title>

        <link rel="stylesheet" href="demo.css" type="text/css" />

    </head>

    <body>

        <div id="test">

            測试zepto源代码

            <span class="aa">22</span>

            <span class="bb">2332</span>

        </div>

        <div class="wrap">content</div>

        <script src="zepto-dev.js"></script>

        <script>

            console.log($('div'));

            console.log($('.aa'));

            console.log($('<div>这是測试内容</div>'));

            console.log($("<span />", { text: "測试測试111", id: "ceshi_111", css: { color: 'red' } }));

            Zepto(function($) {

                console.log('Ready to Zepto!');

            });

        </script>

        <script>

            console.log($.camelCase('hello-there-body'));

            console.log($.contains($('#test')[0], $('.aa')[0]));

            $.each(['a', 'b', 'c'], function(index, item) {

                console.log('item %d is: %s', index, item);

            });

            var hash = { name: 'zepto-dev.js', size: 'micro' };

            $.each(hash, function(key, value) {

                console.log('%s: %s', key, value);

            });

        </script>

    </body>

</html>

zepto-dev.js源代码:
var Zepto = (function() {

    /**

     * 变量初始化

     */

    var $;

    var zepto = {};

    var fragmentRE = /^\s*<(\w+|!)[^>]*>/;

    var singleTagRE = /^<(\w+)\s*\/?>(?:<\/\1>|)$/;

    var tagExpanderRE = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig;

    var undefined;

    var emptyArray = [];

    var slice = emptyArray.slice;

    var cssNumber = {

        'column-count': 1,

        'columns': 1,

        'font-weight': 1,

        'line-height': 1,

        'opacity': 1,

        'z-index': 1,

        'zoom': 1

    };

    // 特殊属性集合

    var methodAttributes = [ 'val', 'css', 'html', 'text', 'data', 'width', 'height', 'offset' ];

    var table = document.createElement('table');

    var tableRow = document.createElement('tr');

    var containers = {

        'tr': document.createElement('tbody'),

        'tbody': table,

        'thead': table,

        'tfoot': table,

        'td': tableRow,

        'th': tableRow,

        '*': document.createElement('div')

    };

    var readyRE = /complete|loaded|interactive/;

    var simpleSelectorRE = /^[\w-]*$/;

    var class2type = {};

    var toString = class2type.toString;

    var camelize;

    var isArray = Array.isArray || function(object) {

        return object instanceof Array;

    };





    /**

     * 检測函数

     */

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

    }

    function isPlainObject(obj) {

        return isObject(obj) && !isWindow(obj) && Object.getPrototypeOf(obj) == Object.prototype;

    }

    function likeArray(obj) {

        return typeof obj.length == 'number';

    }

    /**

     * 字符串替换

     * 使用replace第二个參数带回调

     */

    function camelize(str) {

        return str.replace(/-+(.)?/g,

            function(match, chr) {

                console.log(chr);

                return chr ? chr.toUpperCase() : '';

            }

        );

    }

    function dasherize(str) {

        return str.replace(/::/g, '/')

            .replace(/([A-Z]+)([A-Z][a-z])/g, '$1_$2')

            .replace(/([a-z\d])([A-Z])/g, '$1_$2')

            .replace(/_/g, '-')

            .toLowerCase()

    }

    function maybeAddPx(name, value) {

        return (typeof value == "number" && !cssNumber[dasherize(name)]) ?

value + "px" : value;

    }

    /**

     * `$.zepto.fragment`须要一个html字符串和一个可选标记名来生成dom

     * 产生的dom返回一个数组形式

     * 该功能能够被插件覆盖

     * 没有覆盖全部浏览器

     */

    zepto.fragment = function(html, name, properties) {

        var dom;

        var nodes;

        var container;

        // 标签特殊化处理

        if (singleTagRE.test(html)) {

            dom = $(document.createElement(RegExp.$1));

        }

        if (!dom) {

            if (html.replace) {

                html = html.replace(tagExpanderRE, "<$1></$2>");

            }

            if (name === undefined) {

                name = fragmentRE.test(html) && RegExp.$1;

            }

            if (!(name in containers)) {

                name = '*';

            }

            container = containers[name];

            container.innerHTML = '' + html;

            dom = $.each(slice.call(container.childNodes), function() {

                container.removeChild(this);

            });

        }

        if (isPlainObject(properties)) {

            nodes = $(dom);

            $.each(properties, function(key, value) {

                if (methodAttributes.indexOf(key) > -1) {

                    nodes[key](value);

                }

                else {

                    nodes.attr(key, value);

                }

            });

        }

        return dom;

    };

    /**

     * `$.zepto.Z`将给定`dom`节点数组的原型赋上`$.fn`提供的全部Zepto函数

     * 请注意。`__proto__`不支持IE浏览器

     */

    zepto.Z = function(dom, selector) {

        dom = dom || [];

        dom.__proto__ = $.fn;

        dom.selector = selector || '';

        return dom;

    };

    /**

     * `$.zepto.isZ`检查给定的对象是一个Zepto的集合,可被插件覆盖

     */

    zepto.isZ = function(object) {

        return object instanceof zepto.Z;

    };

    /**

     * `$.zepto.init`是Zepto借鉴jQuery的`$.fn.init`方法

     * 採用css选择器和一个可选的上下文(处理各种特殊情况)

     * 该方法可被插件覆盖

     */

    zepto.init = function(selector, context) {

        // 假设没有给出,返回一个空的Zepto集合

        if (!selector) {

            return zepto.Z();

        }

        // 检測字符串类型

        else if (typeof selector == 'string') {

            selector = selector.trim();

            /**

             * 假设是一个HTML片段,创建节点注意,在chrome21和FF15版本号。

             * DOM错误12不是以<被抛出

             */

            if (selector[0] == '<' && fragmentRE.test(selector)) {

                dom = zepto.fragment(selector, RegExp.$1, context);

                selector = null;

            // 假设存在一个上下文环境,建立收集。并从中选择节点

            } else if (context !== undefined) {

                return $(context).find(selector);

            // 假设是一个css选择器。用它来选择节点

            } else {

                dom = zepto.qsa(document, selector);

            }

        // 假设一个函数存在,在domready就绪后触发

        } else if (isFunction(selector)) {

            return $(document).ready(selector);

        }

        // 假设zepto已经收集给出,直接返回

        else if (zepto.isZ(selector)) {

            return selector;

        } else {

            // 假设节点已经为数组,进行聚合

            if (isArray(selector)) {

                dom = compact(selector);

            }

            // 包装DOM节点

            else if (isObject(selector)) {

                dom = [selector];

                selector = null;

            }

            // 假设是一个HTML片段,对该片段创建节点

            else if (fragmentRE.test(selector)) {

                dom = zepto.fragment(selector.trim(), RegExp.$1, context);

                selector = null;

            }

            // 假设存在上下文环境,先建立收集。并从中选择节点

            else if (context !== undefined) {

                return $(context).find(selector);

            }

            // 假设是一个css选择器。用它来选择节点

            else {

                dom = zepto.qsa(document, selector);

            }

        }

        // 对发现的节点创建一个新的Zepto集合

        return zepto.Z(dom, selector);

    };

    // `$`作为Zepto的元对象。当调用`$`该函数将转由`$.zepto.init`处理

    $ = function(selector, context) {

        return zepto.init(selector, context);

    };

    /**

     * `$.zepto.qsa`是Zepto的css选择器,使用document.querySelectorAll及特殊情况

     * 可被插件覆盖

     */

    zepto.qsa = function(element, selector) {

        var found;

        var maybeID = (selector[0] == '#');

        var maybeClass = !maybeID && selector[0] == '.';

        // 确认下标从1開始后的字符串

        var nameOnly = maybeID || maybeClass ?

selector.slice(1) : selector;

        var isSimple = simpleSelectorRE.test(nameOnly);

        return (isDocument(element) && isSimple && maybeID) ?

            ((found = element.getElementById(nameOnly)) ? [found] : []) :

            slice.call((isSimple && !maybeID) ?

                maybeClass ?

element.getElementsByClassName(nameOnly) : // class名称

                element.getElementsByTagName(selector) : // tag名称

                element.querySelectorAll(selector) // 查询全部匹配到的

            );

    };

    /**

     * $.contains(parent, node); 演示样例$.contains($('#test')[0], $('.aa')[0])

     * 检查父节点是否包括给定的dom节点,假设两者是同样节点,返回false

     * return {boolean} true/false

     */

    $.contains = document.documentElement.contains ?

        function (parent, node) {

            return parent !== node && parent.contains(node);

        } :

        function (parent, node) {

            while (node && (node = node.parentNode)) {

                if (node === parent) {

                    return true;

                }

            }

            return false;

        };

    function setAttribute(node, name, value) {

        value == null ? node.removeAttribute(name) : node.setAttribute(name, value);

    }

    // 函数參数

    function funcArg(context, arg, idx, payload) {

        return isFunction(arg) ? arg.call(context, idx, payload) : arg;

    }

    $.type = type;

    $.isFunction = isFunction;

    $.isWindow = isWindow;

    $.isArray = isArray;

    $.isPlainObject = isPlainObject;

    $.camelCase = camelize;

    /**

     * Zepto对象迭代器

     * @param {object|array} elements 数据对象

     * @param {function} callback 回调函数

     * return {object|array} elements 数据对象

     */

    $.each = function(elements, callback) {

        var i;

        var key;

        // 数组检測

        if (likeArray(elements)) {

            for (i = 0; i < elements.length; i++) {

                if (callback.call(elements[i], i, elements[i]) === false) {

                    return elements;

                }

            }

        } else {

            for (key in elements) {

                if (callback.call(elements[key], key, elements[key]) === false) {

                    return elements;

                }

            }

        }

        return elements;

    };

    // 配置类型映射

    $.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) {

        class2type["[object " + name + "]"] = name.toLowerCase();

    });

    /**

     * 定义的方法,适用于全部的Zepto对象

     */

    $.fn = {

        ready: function(callback) {

            // 检查document.body存在且文档渲染完毕

            if (readyRE.test(document.readyState) && document.body) {

                callback($);

            } else {

                document.addEventListener('DOMContentLoaded', function() {

                    callback($);

                }, false);

            }

        },

        each: function(callback) {

            emptyArray.every.call(this, function(el, idx) {

                return callback.call(el, idx, el) !== false;

            });

            return this;

        },

        text: function(text) {

            return 0 in arguments ?

this.each(function(idx) {

                    var newText = funcArg(this, text, idx, this.textContent);

                    this.textContent = (newText == null) ? '' : '' + newText;

                }) :

                (0 in this ? this[0].textContent : null);

        },

        attr: function(name, value) {

            var result;

            return (typeof name == 'string' && !(1 in arguments)) ?

                (!this.length || this[0].nodeType !== 1 ? undefined :

                    (!(result = this[0].getAttribute(name)) && name in this[0]) ? this[0][name] : result

                ) :

                this.each(function(idx){

                    if (this.nodeType !== 1) {

                        return;

                    }

                    if (isObject(name)) {

                        for (key in name) {

                            setAttribute(this, key, name[key]);

                        }

                    } else {

                       setAttribute(this, name, funcArg(this, value, idx, this.getAttribute(name)));

                    }

                });

        },

        // css属性设置

        css: function(property, value) {

            if (arguments.length < 2) {

                var element = this[0];

                var computedStyle = getComputedStyle(element, '');

                if (!element) {

                    return;

                }

                if (typeof property == 'string') {

                    return element.style[camelize(property)] || computedStyle.getPropertyValue(property);

                } else if (isArray(property)) {

                    var props = {};

                    $.each(isArray(property) ? property : [property], function(_, prop) {

                        props[prop] = (element.style[camelize(prop)] || computedStyle.getPropertyValue(prop));

                    });

                    return props;

                }

            }

            var css = '';

            if (type(property) == 'string') {

                if (!value && value !== 0) {

                    this.each(function() {

                        this.style.removeProperty(dasherize(property));

                    });

                } else {

                    css = dasherize(property) + ":" + maybeAddPx(property, value);

                }

            } else {

                for (var key in property) {

                    if (!property[key] && property[key] !== 0) {

                        this.each(function() {

                            this.style.removeProperty(dasherize(key));

                        });

                    } else {

                        css += dasherize(key) + ':' + maybeAddPx(key, property[key]) + ";";

                    }

                }

            }

            return this.each(function() {

                this.style.cssText += ';' + css;

            });

        }

    };

    // 继承

    zepto.Z.prototype = $.fn;

    $.zepto = zepto;

    return $;

})();





// 全局变量接口

window.Zepto = Zepto;

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


浏览器输出结果:










Zepto源代码分析之二~三个API的更多相关文章

  1. Zepto源代码分析一~核心方法

    今天抽出时间复习了一下Zepto的源代码,依照自己的理解进行凝视. 欢迎大家拍砖. 源代码版本号:v1.1.4 源代码下载地址:http://zeptojs.com/ 分析总体代码之后,整理出架构图: ...

  2. hostapd源代码分析(二):hostapd的工作机制

    [转]hostapd源代码分析(二):hostapd的工作机制 原文链接:http://blog.csdn.net/qq_21949217/article/details/46004433 在我的上一 ...

  3. Redis源代码分析(二十八)--- object创建和释放redisObject物

    今天的学习更有效率.该Rio分析过,学习之间的另一种方式RedisObject文件,只想说RedisObject有些生成和转换.都是很类似的.列出里面长长的API列表: /* ------------ ...

  4. Redis源代码分析(二十)--- ae事件驱动

    事件驱动的术语出现更频繁.听起来非常大的,今天我把Redis内部驱动器模型来研究它,奖励的感觉啊.一个ae.c主程序,加4文件的事件类型,让你彻底弄清楚,Redis是怎样处理这些事件的. 在Redis ...

  5. Redis源代码分析(二十四)--- tool工具类(2)

    在上篇文章中初步的分析了一下,Redis工具类文件里的一些使用方法,包含2个随机算法和循环冗余校验算法,今天,继续学习Redis中的其它的一些辅助工具类的使用方法.包含里面的大小端转换算法,sha算法 ...

  6. Redis源代码分析(二十二)--- networking网络协议传输

    上次我仅仅分析了Redis网络部分的代码一部分,今天我把networking的代码实现部分也学习了一遍,netWorking的代码很多其它偏重的是Clientclient的操作.里面addReply( ...

  7. PostgreSQL的 initdb 源代码分析之二十五

    继续分析: make_postgres(); 展开: 目的是创建postgres数据库. cmd是:/home/pgsql/project/bin/postgres" --single -F ...

  8. PostgreSQL的 initdb 源代码分析之二十四

    继续分析: make_template0(); 展开: 无需再作解释,就是创建template0数据库 /* * copy template1 to template0 */ static void ...

  9. PostgreSQL的 initdb 源代码分析之二十三

    继续分析: vacuum_db(); 展开: cmd是:/home/pgsql/project/bin/postgres" --single -F -O -c search_path=pg_ ...

随机推荐

  1. vuejs 基础总结(one)

    vuejs 入门知识点 1.active-class 是哪个组件的属性?嵌套路由怎么定义 (1).active-class 是 vue-router 模块的 router-link 组件的属性 (2) ...

  2. js 学习思维导图

  3. Html 播放 mp4格式视频提示 没有发现支持的视频格式和mime类型

    转自原文 Html 播放 mp4格式视频提示 没有发现支持的视频格式和mime类型 播放mp4格式的时候提示 Html 播放 mp4格式视频提示 没有发现支持的视频格式和mime类型 原因是在IIS中 ...

  4. Ruby print

    Ruby print

  5. 【struts2】struts2中的流接收与流发送

    [前言]在我们的struts2后端中,实现流的接收和发送.就能够实现向server传视频流以及下载图片. [流接收] 如今举一个传公钥的样例.struts2用一个action接收Key,而Key就是用 ...

  6. 整数翻转C++实现 java实现 leetcode系列(七)

    给出一个 32 位的有符号整数,你需要将这个整数中每位上的数字进行反转. 示例 1: 输入: 123 输出: 321 示例 2: 输入: -123 输出: -321 示例 3: 输入: 120 输出: ...

  7. Windows 安装PostgreSQL

    下载二进制包:https://www.enterprisedb.com/download-postgresql-binaries 直接解压到C盘 Microsoft Windows [版本 6.3.9 ...

  8. MariaDB GALERA 集群双节点部署

    节点1:10.2.2.41 节点2:10.2.2.42 软件: mariadb-galera-10.0.22-linux-x86_64.tar.gz #galera相关参数:(两个节点配置文件类似) ...

  9. SpringCloud学习笔记(4)----Spring Cloud Netflix之Eureka的配置

    1. Eureka监控配置 Eureka的客户端需要加入依赖 <dependency> <groupId>org.springframework.boot</groupI ...

  10. express + jqPaginator 分页展示内容

    写在前面的话 分页展示内容也是我们在页面开发中经常会遇到的需求 前端页面利用jqPaginator这个jquery插件来编写 后端利用mysql存储数据 开始敲代码 回顾sql知识 首先让我们回顾一下 ...