(二)解决前6条
2012-02-12 14:37 kwjlk 阅读(417) 评论(1) 收藏 举报1.window.undefined = window.undefined
make the global window.undefined as real undefined value.
未定义,当属性没有定义过(不存在)时访问该属性则会返回值:未定义。虽然window.undefined一定会被浏览器定义成了"未定义"的值,但是谁会知道哪个别有用心的浏览器(火狐)是个例外呢。所以,这一段代码做了双重保证。定义了window.undefined属性为未定义的浏览器中执行这一句代码没有任何改变,在没有定义window.undefined属性的浏览器中执行后window.undefined 则会被定义并且赋值成未定义。网上有提到,对于没有定义window.undefined属性的浏览器判断一个是否是未定已要使用如下判断 if(window.p == 'undefined')。
2.对$元符号的处理。
// Map over the $ in case of overwrite
if ( $ )
jQuery._$ = $;
// Map the jQuery namespace to the '$' one
var $ = jQuery;
如果已经定义过美元符号了,则将已经定义存在的美元符号赋值到jQuery._$上。然后重新定义美元符号$为jQuery。这里需要特别的注意在将jQuery赋值到$上时使用了var 重新定义$美元符号的语法。否则将会把jQuery._$一起覆盖:
// Map over the $ in case of overwrite
if ( $ )
jQuery._$ = $;
// Map the jQuery namespace to the '$' one
$ = jQuery; //这一句将会导致 jQuery._$ = $ = jQuery的效果,而不是 jQuery._$ = old $ , $ = jQuery 的效果。
3.jQuery(a,c) 与 jQuery.fn = jQuery.prototype = { ... }
看着看着发现,jQuery(a,c)中的实现引用了后面定义的很多函数,而jQuery.fn = jQuery.prototype = {...}中代码量也很大,而且也引用到了后面定义的函数。相反,jQuery.extend 的定义则相对简单很多,于是选择阅读jQuery.extend中的代码。
4.jQuery.extend 方法
在分析jQuery.extend之前,我们需要理解jQuery.fn = jQuery.prototype ={ ... } 的写法
js中的prototype在面向对象方面有很大作用。你可以在网上查阅一下这方面的相关资料。经由jQuery.fn = jQuery.prototype = { ... } 我们在之后对jQuery拓展方法时就可以使用 jQuery.method = jQuery.fn.method = function(){ ... }的形式了。jQuery.method 仅会让方法成为jQuery本身的方法,而jQuery.fn.method则仅会让方法成为jQuery对象的方法。两者同时使用才会达到jQuery自身和jQuery对象同时拥有该方法的效果。我们通过如下代码来演示这种效果:
function jQuery(){} // 一个空的叫做jQuery的类型
var omygod = function(){alert('God bless you.');} //定一个函数
jQuery.me = omygod;
alert(jQuery.me); // 弹窗显示 function(){alert('God bless you.');}
var jq = new jQuery();
alert(jq.me); // 弹窗显示 undefined
jQuery.fn = jQuery.prototype;
jQuery.fn.me = omygod;
alert(jq.me); // 弹窗显示 function(){alert('God bless you.');}
jQuery.fn.you = 'hi'
alert(jq.you) // 弹窗显示 hi
alert(jQuery.you) //弹窗显示 undefined
如果你有更多的疑问点,请提出你的问题或者自行编写代码进行验证。
接下来我们看一下jQuery中伟大的extend方法,这个方法功能强大实现怎么可能是这样的?
jQuery.extend = jQuery.fn.extend = function(obj,prop) {
if ( !prop ) { prop = obj; obj = this; }
for ( var i in prop ) obj[i] = prop[i];
return obj;
};
真是不知者有罪啊,如果不知道怎么实现的将会造成多大的罪孽。——by kwjlk
jQuery.extend实现虽然简单,但是其强大的功能正是印证了js的强大。首先这里面有三个重要点:
- js中的真假世界观,即if(!prop)的判断何时是if(true)何时是if(false)。
- js中可以以数组形式访问和赋值对象的属性。
- js 中 for..in 数组遍历(基于第二点,则也可以遍历对象的属性)
对于第一点,在js中 null , undefined , false , 字符串空,数字0 均为false,非false则为true。
接下来研究如上代码的实现逻辑。首先第一个判断if(!prop){prop = obj,obj = this} 这是的当!prop计算为真(一般为没有传入prop参数)时则将obj对象的属性拓展到extend的调用者身上。接下来我们通过代码分析extend的可能调用场景:
先看如下两段代码:
第一段代码:
var obj = {}
obj['name'] = 'object';
alert(obj.name); // 弹窗显示 object
var nonObj = "12";
nonObj['name'] = 'none object';
alert(nonObj.name); //弹窗显示 none object
以上代码说明,对于非对象性的变量,使用var['key'] = 'value' 的形式并不报错,但是调用var.key时key是undefined。这就是,在extend真正对变量进行属性拓展时,如果目的变量是非对象变量则等同于没有做任何操作。于是在讨论中可以把extend最终作用对象分为对象和非对象,而对非对象的讨论则没有意义。至于那些是非对象呢?我们通过如下代码展示:
//此段代码有待商榷,希望有志认识能够提供指正
var nonObj;
nonObj = null;
nonObj = undefined;
nonObj = 'this is a string';
nonObj = 100;
nonObj = 100.9;
nonObj = ture;
nonObj = false;
第二段代码:
var nonObj;
nonObj = null;
nonObj = undefined;
nonObj = 100;
nonObj = 100.9;
nonObj = ture;
nonObj = false;
for(var i in nonObj){
alert('not here'); //这段代码不会被执行
}
nonObj = 'st';
for(var i in str){
alert(i+'-'+str[i]); // 弹窗显示 0-s 1-t
}
nonObj[1] = 'b';
alert(nonObj); //弹窗显示 st
如上代码说明,对于非字符串的非对象变量,for ... in 也不会起到任何效果,而字符串就是一个字符数组。并且,字符串变量不能通过str[index] = char 的形式改变其值。
总结extend的可能调用场景为
| obj | prop | 结果 |
|---|---|---|
| 对象 | 对象 | 将prop的属性拓展到对象obj身上 |
| 对象 | 非对象真(即if(!prop)不成立),且不为字符串 | 无操作 |
| 对象 | 字符串 | 对象obj以obj[index] = char 的形式存储字符串,但对象obj不会变成字符串 |
| 字符串 | 任意值 | obj仍旧为字符串,值无变化 |
当prop为非对象假时(即if(!prop)成立),obj指向当前extend的调用者,prop指向原obj对象。再次套用上表。
8. new function(){} 的神奇用法
当对象对象对象,脑子里盘旋的全是对象的时候。在Chrome控制台敲入了一段测试代码new function(){} ,Chrome控制台给出的返回结果为Object。顿时,我就明白了new function(){} 与 (function(){})()实现了一样的效果(这里涉及到了js中的匿名函数,还可以发散一下js中的闭包),即定义函数后立即执行。但两者之间孰优属劣呢?
浙公网安备 33010602011771号