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+'\n'+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
相關文章
相關標籤/搜索