jQuery 源码学习笔记

时间:2021-05-11 04:56:53
//检测 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