《jQuery内核详解与实践》--读书笔记

第二章 jQuery技术解密

2.2 jQuery原型技术分解

2.2.1 起源–原型继承

var $ = jQuery = function(){
    // 函数体
}
jQuery.fn = jQuery.prototype = {
    jquery: "1.3.2",
    size: function(){
        return this.length;
    }
}

2.2.2 生命–返回实例

var $ = jQuery = function(){
    return jQuery.fn.init();
}
jQuery.fn = jQuery.prototype = {
    init:function(){
        return this;  //this指向jQuery.prototype
    },
    jquery:"1.3.2",
    size: function(){
        return this.length;
    }
}
alert($().jquery);  //"1.3.2"

2.2.3 学步–分隔作用域

var $ =jQuery = function(){
    //jQuery框架精彩之处
    //将jQuery.fn.init作为构造函数,此处返回init的实例,达到分离作用域的作用,方便调用
    return new jQuery.fn.init();
}
jQuery.fn = jQuery.prototype = {
    init : function(){
        this.length = 0;
        this.test = function(){
            return this.length;
        }
        return this;
    },
    jquery: "1.3.2",
    length: 1,
    size: function() {
        return this.length;
    }
}
//无法访问jQuery.fn对象的属性或方法
alert( $().jquery );    //返回undefined    
alert( $().test() );     //返回0
alert( $().size() );     //抛出异常

2.2.4 生长–跨域访问

var $ =jQuery = function(){
    return new jQuery.fn.init();
}
jQuery.fn = jQuery.prototype = {
    init : function(){
        this.length = 0;
        this.test = function(){
            return this.length;
        }
        return this;
    },
    jquery: "1.3.2",
    length: 1,
    size: function() {
        return this.length;
    }
}
//jQuery框架精彩之处
//使用jquery的原型对象覆盖init的原型对象,
//这样通过init创建出来的实例对象就能访问到jQuery的原型方法及属性
jQuery.fn.init.prototype = jQuery.fn;     
alert( $().jquery );     //返回"1.3.2"
alert( $().test() );     //返回0
alert( $().size() );     //返回0

2.2.5 成熟–选择器

<div></div>
<div></div>
<div></div>
<script type="text/javascript">
var $ =jQuery = function(selector, context ){       //定义类
    return new jQuery.fn.init(selector, context );  //返回选择器的实例
}
jQuery.fn = jQuery.prototype = {    //jQuery类的原型对象
    init : function(selector, context){     //定义选择器构造器
        selector = selector || document;        //设置默认值为document
        context = context || document;  //设置默认值为document
        if ( selector.nodeType ) {  //如果选择符为节点对象
            this[0] = selector;     //把参数节点传递给实例对象的数组
            this.length = 1;    //并设置实例对象的length属性,定义包含元素个数
            this.context = selector;    //设置实例的属性,返回选择范围
            return this;    //返回当前实例
        }
        if ( typeof selector === "string" ) {   //如果选择符是字符串
            var e = context.getElementsByTagName(selector);     //获取指定名称的元素
            for(var i = 0;i<e.length;i++){  //遍历元素集合,并把所有元素填入到当前实例数组中
                this[i] = e[i];
            }
            this.length = e.length;     //设置实例的length属性,即定义包含元素的个数
            this.context = context;     //设置实例的属性,返回选择范围
            return this;    //返回当前实例
        } else{
            this.length = 0;    //否则,设置实例的length属性值为0
            this.context = context;     //设置实例的属性,返回选择范围
            return this;    //返回当前实例
        }
    },
    jquery: "1.3.2",
    size: function() {
        return this.length;
    }
}
jQuery.fn.init.prototype = jQuery.fn;
alert( $("div").size() );   //返回3
</script>

2.6 延续–迭代器

<div></div>
<div></div>
<div></div>
<script type="text/javascript">
var $ = jQuery = function(selector, context) {
    return new jQuery.fn.init(selector, context);
}
jQuery.fn = jQuery.prototype = {
    init: function(selector, context) {
        //参阅上节示例
    },
    html: function(val) {
        jQuery.each(this, function(val) {
            this.innerHTML = val;
        }, val);
    }
}
jQuery.fn.init.prototype = jQuery.fn;

jQuery.each = function(object, callback, args) {
    for (var i = 0; i < object.length; i++) {
        callback.call(object[i], args);
    }
    return object;
}

$("div").html("测试代码");
</script>

2.2.7 延续–功能扩展

var $ = jQuery = function(selector, context) {
    return new jQuery.fn.init(selector, context);
}
jQuery.fn = jQuery.prototype = {
    init: function(selector, context) {},
    html: function(val) {}
}
jQuery.fn.init.prototype = jQuery.fn;
jQuery.extend = jQuery.fn.extend = function(obj) {
    for (var prop in obj) {
        //jquery精彩之处
        //把指定对象的方法赋值给jQuery或jQuery.fn,使得jquery可以不断扩充
        this[prop] = obj[prop];
    }
    return this;
}
jQuery.each = function(object, callback, args) {}

jQuery.fn.extend({
    test: function() {
        alert("测试扩展功能");
    }
})

2.2.8 延续–参数处理

var $ = jQuery = function(selector, context) {
    return new jQuery.fn.init(selector, context);
}
jQuery.fn = jQuery.prototype = {
    init: function(selector, context) {},
    html: function(val) {},
    setOptions: function(options) {
        this.options = {
            StartColor: "#000",
            EndColor: "#DDC",
            Background: false,
            Step: 20,
            Speed: 10
        };
        jQuery.extend(this.options, options || {});
    }
}
jQuery.fn.init.prototype = jQuery.fn;

jQuery.extend = jQuery.fn.extend = function(destination, source) {
    for (var property in source) {
        destination[property] = source[property];
    }
    return destination;
}

2.2.9 涅槃–名字空间

(function(){
    var window = this,undefined,_jQuery = window.jQuery,_$ = window.$,
    jQuery = window.jQuery = window.$ = function(selector, context) {
        return new jQuery.fn.init(selector, context);
    };
    jQuery.fn = jQuery.prototype = {}
})()

2.3 破解jQuery选择器接口

jQuery实例对象其实就是jQuery.fn.init构造器创建的对象,通过jQuery.fn.init.prototype = jQuery.fn使得
jQuery实例对象继承了jQuery对象的方法。

第三章 高效选择的技巧与原理

3.2 简单选择器

3.2.1 选择指定ID元素

javascript实现方法document.getElementById("id")
javascript实现方法document.querySelector("#id")
jqury实现方法$('#id')
执行效率比较分析

window.onload = function(){
    for(var i=0;i<1000;i++){        
        var span = document.createElement("span");
        span.setAttribute("id","span" + i);
        document.getElementsByTagName("body")[0].appendChild(span);       
    }
    var a = [];
    console.time("time");
    for(var j=0;j<1000;j++){       
        var b = document.getElementById("span"+j);     //time: 1.201ms
        // var b = document.querySelector("#span"+j);  //time: 5.045ms
        //var b = $("#span"+j);                        //time: 5.092ms
        a.push(b);
    }
    console.timeEnd("time");
}

由于jQuery需要对参数字符串进行分析,并匹配出所传递的参数值是ID值,然后才能调用getElementById()方法获取该ID元素,所以花费时间会更多

3.2.3 选择指定类元素

javascript实现方法

document.getElementsByClassName = function(className) { 
    var el = [],
        _el = document.getElementsByTagName('*');
    for (var i=0; i<_el.length; i++ ) {
       if (_el[i].className == className ) {
           el[el.length] = _el[i];
        }
   }
   return el;
}

javascript实现方法document.querySelector(".className")
jquery实现方法$(.className)
执行效率比较分析

document.getElementsByClassName = function(className) { 
    var el = [],
        _el = document.getElementsByTagName('*');
    for (var i=0; i<_el.length; i++ ) {
       if (_el[i].className == className ) {
           el[el.length] = _el[i];
        }
   }
   return el;
}
window.onload = function() {
    for (var i = 0; i < 500; i++) {
        var span = document.createElement("span");
        span.setAttribute("class", "red");
        document.getElementsByTagName("body")[0].appendChild(span);
    }
    var a = [];
    console.time("time");
    for (var j = 0; j < 500; j++) {
        //var b = document.getElementsByClassName("red");//time: 132.483ms
        var b = document.querySelector(".red");          //time: 0.867ms
        //var b = $(".red");                             //time: 140.824ms
        a.push(b);
    }
    console.timeEnd("time");  
}

在类的查询中document.querySelector方法最快,IE8+都能兼容,所以实际使用中选择速度最快的那个了

第八章 高效开发和使用插件

8.1创建jQuery插件

8.1.2解析jQuery插件机制

jQuery.extend()能够创建全局函数或选择器
在实际开发中,常使用jQuery.extend()方法作为插件方法传递系列选项结构的参数

var options = jQuery.extend({},{
    name1 : value1;
    name2 : value2;
    name3 : value3;
    },options);

jQuery.fn.extend()能够创建jQuery对象方法

8.1.3 创建jQuery全局函数

建议把属于自己的插件都封装在一个对象中

jQuery.css8 = {
    minValue : function(a, b){
        return a < b ? a : b;
    },
    maxValue : function(a, b){
        return a < b ? b : a;
    }
}

8.1.4 使用jQuery.fn对象创建jQuery对象方法

jQuery.fn.test = function(){
    return this.each(function(){
        alert(this.nodeName);
    });
}

8.1.5 使用extend()方法创建jQuery对象方法

jQuery.fn.extend({
    test : function(){
        return this.each(function(){
            alert(this.nodeName);
        });
    };
})

8.1.6 创建自定义选择器

jQuery选择器会使用一组正则表达式来分析选择符,然后针对所解析出来的每一个选择符执行一个函数,这个函数被称为选择器函数,最后根据这个选择器函数的返回值是否为true决定是否保留当前元素,这样就可以找到所要匹配的元素节点。
其正则表达式直接量如下:

match{
    POS:/(nth|eq|qt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/   ???
}

自定义:ge(大于等于)和:le(小于等于)选择器

jQuery.extend(jQuery.expr[":"],{
    le:function(elem, i, match){
        return i < match[3] - 0 || i == match[3] - 0;  //match[3] - 0强制转换为数值类型
    },
    ge:function(elem, i, match){
        return i > amtch[3] - 0 || i == match[3] - 0;
    }
})

8.1.14 创建jQuery插件应注意的问题

  1. 命名规则
    jquery.pluginName.js
  2. 基本思想
    所有新方法都附加到jQuery.fn对象上,所有新功能都附加到jQuery对象上
  3. 方法内的this关键字
    this关键字用于引用jQuery对象,在this.each()方法体内,this是引用当前匹配的DOM元素对象
  4. 迭代匹配元素
    使用this.each()迭代匹配元素
  5. 方法的返回值
    所有方法都必须放回jQuery对象
  6. 方便压缩
    所有方法或函数,末尾必须加分号(😉
  7. 建议框架
(function($, window, document, undefined){

})(jQuery, window, document);