zoukankan      html  css  js  c++  java
  • jQuery 源码学习笔记

    //检测 window 中新增的对象
    //first
    var oldMap = {};
    for(var i in window)
    {
        oldMap[i] = 1;
    }
    
    //second
    for(var i in window)
    {
        if(oldMap[i]) continue;
        alert(i);
    }
    
    $()选择器获取到的既不是一个dom元素,也不是节点列表,而是一个新的对象
    
    $() 不传入任何参数会返回一个空的jquery对象
    
    
    //google  cdn获取jquery  
    <script type="text/javascript" src="http://www.google.com/jsapi"></script>
    <script>
        google.load("jquery",'1.4.2');
        google.setOnLoadCallback(function(){alert('aa'+$)}); 
    </script>
    
    //这种写法更好
    $ = [1,2];
    jQuery(function($){
        //自动传入jQuery对象,即使外边的$被覆盖依然可以使用$
        alert($);
    })
    
    //创建一个元素,同时给他添加一些属性和方法
    
    $("<input>", {
      type: "text",
      val: "Test",
      focusin: function() {
        $(this).addClass("active");
      },
      focusout: function() {
        $(this).removeClass("active");
      }
    }).appendTo("form");
    
    //获取select标签的值,当为单选时为一个数值,当为多选时则会返回一个数组,
    
    //设置多选传入数组 $("select").val([1,2,3]);
    
    $("select option:selected").each(function(){  
        alert(this.value);
    })
    
    
    //绑定事件时传入参数,很好的解决了闭包产生的问题
    var message = 'Spoon!';
    
    $('#foo').bind('click', {msg:message}, function(evt) {
    
        //访问传入参数的方式
        alert(evt.data.msg);
        
    });
    message = 'sjk';
    
    在事件处理函数内返回false就等价于执行事件对象上的.preventDefault()[ie:evt.returnValue=false;]和.stopPropagation()[ie:evt.cancelBubble=true;]
    
    jq绑定的事件只能用自身的方法来触发,但js绑定的事件同样可以用jq来触发
    
    $("#song").click(function(evt){
        alert(evt.originalEvent); //原始的事件对象
        alert('click');    
    })
    
    //事件绑定外边的一个函数
    function test(evt, msg){
        alert(evt);
        alert(msg);    
        alert(this.innerHTML);
    }
    document.getElementById('song').onclick = function(evt){
        test.call(this, evt, 'ok');    //important
    };
    
    //    trigger传入参数
    $("#song").click( function (event, a, b) {
      // 一个普通的点击事件时,a和b是undefined类型
      // 如果用下面的语句触发,那么a指向"foo",而b指向"bar"
          alert(a+'
    '+b);
    } ).trigger("click", ["foo", "bar"]);
    
    
    live事件委托的原理
    $(document).bind("click", function (e) {
        $(e.target).closest("li").toggleClass("hilight");
    });
    
    //新发现mouse事件 mouseenter / mouseleave
    
    jquery返回的对象非常类似数组,但并不是继承自数组 instanceof  Array
    
    //会自动把数组的下标赋值到this下面
    [].push.apply(this,ary);
    
    //jquery对象实现原理
    function list(ary)
    {
        this.ary = ary;
        [].push.apply(this,ary);
    }
    
    list.prototype = {
        attr:function(){
            for(var i=0;i<this.ary.lenght;i++){
                this.ary[i][name] = value;
            }    
        },
        get:function(index){
            if(index === undefined) return this.ary;
            else{
                return this.ary[index];
            }
        },
        push:[].push,
        shift:[].shift
    }
    
    var l = new list([1,2,3]);
    l.push(4);
    l.push(5);
    console.dir(l);
    
    下面的script标签会等上面的script标签中的内容全部加载完毕后才执行
    
    xpath:比css选择器更为强大些
    
    //改变某个函数的this上下文
        function closure(fn,scope)
        {
            return function(){
                fn.apply(scope, arguments);
            }
        }
    
    //调用一个对象上指定的方法     ps:貌似没啥用?
    function invoke(obj, methodName)
    {
        return function(){
            obj[methodName].apply(obj,arguments);
        };
    }
    
    都是返回一个经过包装过的函数
    
    //给函数增加属性
    function test(){
        arguments.callee.guid = 1;
    }
    
    var fn = function(){
        arguments.callee.guid = 1;
    }
    //fn();#必须执行后才能有此属性
    alert(fn.guid);
    
    //一种变通的方式 给匿名 函数增加属性
    var fn = function(){
        var anony = function(){
            // your code
        }
        anony.guid = 1;
        return anony;
    }
    
    
    $.proxy(fn,scope)用法
    $(function(){
        function test(){
            alert(this.html());    
        }
        var h = $(":header");
        h.click($.proxy(test,h)) //改变this的值
        
        alert(test.guid); //每个函数赋值一个guid,当此函数经过闭包处理后返回的函数仍旧此函数的guid相同,
        可以用guid来判断这两个函数是相同的(一般情况下我们无法比较两个函数是否相同)
    })
    
    w3c浏览器:
        addEventListener
        removeEventListener
    IE:
        attachEvent 
        detachEvent
    
    
    //closest对于处理事件委托非常有用, 可以实现 live 、delegate效果
    $(document).bind("click", function (e) {
        $(e.target).closest("li").toggleClass("hilight");
    });
    
    解决$命名空间冲突的问题
    jQuery.noConflict();
    jQuery(function($){  传入一个函数后,jquery会自动把他的全局命名空间($),传入次函数的参数中
        
        var len = $("ul li").length;
        console.log(len);
    })
    
    在引入jquery文件后立刻调用
    //释放$命名空间
    jQuery.noConflict();
    
    //释放jQuery命名空间
    jQuery.noConflict(true);
    
    
    一般写jquery代码时可以把$全局命名空间释放掉,这样就避免了和其他插件的冲突
    $可以用局部的那个
    
    //数据缓存
    $("#song").data("title", 'title');
    $("#song").data("age", 27);
    
    //不传入参数则会返回一个js对象,并不是dom对象
    var obj = $("#song").data();
    
    alert(obj.title);
    alert(obj.age);    
    
    //可以传入obj,键值对
    $("#song").data({name:12,age:27});
    
    
    源码分析:
    //注册命名空间
    function test(){}
    
    var _nspool = {};
    
    test.ns = function(name, value){
        var names = name.split('.');
        o = window;
        for(var i=0;i<names.length;i++)
        {
            if(!o[names[i]])
            {
                o[names[i]] = {};
            }
            o = o[names[i]];
            
            _nspool[name] = o[names[i]];
            o[names[i]] = value;
        }
    }
    
    test.ns('a.b.c', 123);
    console.dir(_nspool);
    
    //反注册时只需要把 _nspool中的key值删除
    
    命名空间太长,可能会引起效率问题,可以把他赋给一个值    
    
    [object Object] [基本类型 构造函数]
    alert({}.toString());
    //数组上的toString方法被改写了,所以我们借用{}上的toString方法
    
    判断是否是一个数组    {}.toString.call([]); // [object Array]
    
    //插件机制
    jQuery本身添加
    jQuery.newMethod = function(){}
    jQuery.extend(obj);
    
    jQuery对象添加
    jQuery.fn = jQuery.fn.init.prototype = function(){}
    jQuery.fn.extend(obj);
    
    
    //extend 函数默认复杂类型以引用传递
    var o1 = {name:1};
    var o2 = {age:{sex:{hel:1}}};
    
    jQuery.extend(o1,o2);
    console.log(o1.age === o2.age);
    
    
    代理函数:把新返回的函数的guid和原函数的guid设置成相同的,这样解除绑定的时候传入原函数即可
    var obj = {
      name: "John",
      test: function() {
        alert( this.name );
        $("#test").unbind("click", obj.test);
      }
    };
    
     $("#song").click( jQuery.proxy( obj, "test" ) );
    
    //以下代码跟上面那句是等价的:
    ("#song").click( jQuery.proxy( obj.test, obj ) );
    
    //可以与单独执行下面这句做个比较。
    $("#song").click( obj.test );
    
     
     原生js实现jquery的proxy方法 
    //改变某个函数的内部this指针
    function closure(fn, scope)
    {
        return function (){
            fn.apply(scope, arguments);
        };
    }
    
    //调用某个对象的某个函数,并将次对象作为方法的作用域
    function invoke(obj, methodName)
    {
        return function(){
            obj.methodName(obj, arguments);
        };
    }
    
    函数绑定原理
    var fns = [],conter = 0;
    //绑定
    function addEvent(){
        fn.guid = counter ++;
        fns[type] = fns[type] || {};
        fns[type][fn.guid] = fn;
        o["on"+type] = function(){
            //遍历 fns
        }
    }
    
    //解除绑定
    function delEvent(o, type, fn)
    {
        delete fns[type][fn.guid];
    }
    
    
    jquery 插件
    轮播器:slideview slinkySlider anythingSlider
  • 相关阅读:
    hdu 5154 拓扑排序
    CSS性能优化的8个技巧
    移动端性能监控方案Hertz
    箴言
    如何使网页的文字不能被复制
    flyio 的请求封装
    vue-cli3.0 环境变量与模式
    函数防抖和函数节流
    CSS世界中那些说起来很冷的知识
    vue多层次组件监听动作和属性
  • 原文地址:https://www.cnblogs.com/siqi/p/3637879.html
Copyright © 2011-2022 走看看