jQuery技术

jquery 美元背后的一点小技巧

字号+ 作者:H5之家 来源:H5之家 2015-10-31 15:15 我要评论( )

在Jquery中,$是JQuery的别名,所有使用$的地方也都可以使用JQuery来替换,如$(

在Jquery中,$是JQuery的别名,所有使用$的地方也都可以使用JQuery来替换,如$('#msg')等同于JQuery('#msg') 的写法。

1、如何给一个id为casper的标签添加一个名为“world”的class

考虑下面一个场景,假设我们页面上有个id为casper的div标签,如下所示

<div id="casper" class="hello">casper是个大傻瓜,啦啦啦啦啦</div>

现在我们想要给它添加一个class,比如“world”,用jquery的话如何实现?很简单,不卖关子

$('#casper').addClass('world');

很好,接下来我们思考:如何不用jquery,我们如何如何实现实现上述功能?最简单的方式:

var node = document.getElementById('casper'); node.className += ' world';

getElementById、getElementsByTagName神马的,名字老长老长的,写着有点不爽,于是把getElementById这个方法用美元($)包装下:

function $(id){ return document.getElementById(id); } $('casper').className += ' world';

className品字符串神马的,jquery的调用方式相比麻烦多了,那再改进下:

function $(id){

var node = document.getElementById(id); node.addClass = function(addName){ node.className += ' ' + addName; }; return document.getElementById(id); } $('casper').addClass('world');

看上去挺像那么一回事了,多优雅的接口啊(热泪盈眶中)~

真的是这样吗,再仔细瞧瞧?于是果断发现不对劲的地方:对于$,每次调用,都会给返回的dom元素上添加一个addClass方法,这对空间来说是极大的浪费。当然,可以将addClass方法抽取出来:

function addClass(className){

//实现略 } function $(id){ var node = document.getElementById(id); node.addClass = addClass; return document.getElementById(id); } $('casper').addClass('world');

原先的空间浪费问题可以在很大程度上得到解决,但明显这解决方法还不够好。如果有那么一种实现方式,让所有的对象实例都共享一个方法。。。

2、jQuery中的实现思路

同样不必卖关子,这里说的就是原型方法,我们再看下jquery的调用方式

$('#casper').addClass('world');

$('#casper')并不是像我们上面那样,简单地将id为casper的元素返回。实际上,$('#casper')返回的是一个jQuery对象,该对象特征如下:

拥有一个length属性,length等于你调用$选中的元素的数目,在$('#casper')中为1

拥有0~n-1的实例属性,分别对应调用$时选中的第1~第n个元素,如本例中$('#casper')[0]即为目标dom元素

拥有一堆原型方法,如常见的addClass、removeClass、bind等

根据上面三点,很容易对我们之前写的代码进行修改,如下:

function $(id){

this[0] = document.getElementById(id); this.length = 1; } $.prototype.addClass = function(className){ this[0].className += ' ' + className; }; var noode = new $('casper'); node.addClass('world');

其实就几行代码的事情,但。。。还是觉得有些不对劲,new $('casper'),平常在用jquery的时候似乎不需要new一下的说,想想看,我们代码中一坨new是多么可怕的事情~

好吧,其实是因为jQuery帮你完成了构造函数调用的这部分工作,这一小小的细节改善对jQuery的流行起到了很大的帮助。按照这个思路,继续修改之前的代码:

function $(id){

if(!(this instanceof $) return new $(id); //加了这么个语句 this[0] = document.getElementById(id); this.length = 1; } //其他一样,节省空间不贴代码

在上面的代码中,只有一点小小的修改,就是加了个判断语句 if(!(this instanceof $)) ,作用在于判断,当$被调用时,究竟是采用以下两种调用方式的哪一种,关于这种判断方式,可参考之前写的《【经验总结】构造函数的强制调用》:

$('casper'),直接调用,于是this为window

new $('casper'),此时$为构造方法,this instanceof $ == true

3、jQuery中的源码实现以及问题所在(俺的疑惑)

罗嗦了这么多,我们看看关于这点,jQuery里是如何实现的,源码大致如下,一些不相干的代码略过:

(function( window, undefined ) {

//去掉无关变量声明等,防止干扰分析 var jQuery = (function() { // Define a local copy of jQuery var jQuery = function( selector, context ) { // The jQuery object is actually just the init constructor 'enhanced' return new jQuery.fn.init( selector, context, rootjQuery ); }, //一堆无关细节暂时略过 jQuery.fn = jQuery.prototype = { constructor: jQuery, init: function( selector, context, rootjQuery ) { //继续略过 } }; // Give the init function the jQuery prototype for later instantiation jQuery.fn.init.prototype = jQuery.fn; return jQuery; })(); window.jQuery = window.$ = jQuery; })( window );

对于研究过jQuery源码或曾经打算研究jQuery源码的同学来说,上面这段代码肯定不会陌生,它有一个特点:看上去比较晦涩,特别是是结合了jQuery源码里面比较诡异的代码缩进~

通过闭包返回的jQuery对象,闭包里面是有jQuery函数定义,jQuery函数里面return了new jQuery.fn.init 。。。快速看懂上面这段代码的秘诀在于:一个支持代码高亮和职能中括号匹配的编辑器,比如webstorm。。。

上面只是开个小玩笑,绕了这么久,无法是想做下面几件事情:

无论有没有new,只要调用$,都给你返回一个jQuery对象(实际上jQuery.fn.init才是实际的构造函数)

将jQuery.fn.init.fn指向jQuery.prototype,这样的话,当我们通过$.fn.newPrototypeAttr 方式向jQuery添加原型属性或方法,其实最终都成为了jQuery.fn.init地原型属性或方法

将constructor属性指向jQuery,不然$('#casper').constructor 获得的会是jQuery.fn.init

个人觉得上面这段代码有些费解,似乎完全可以采用相对不那么曲折的方式实现,如下所示,其实思路都是相同的:

然后,就是添加各种原型方法了,兼容性处理和优雅的API,这块才是精华,这里还没讲到。

(function(){

var jQuery = function(id){ return new _jquery(id); }; var _jquery = function(id){ //此处各种选择分支神马的都忽略~ this[0] = document.getElementById(id); this.length = 1; }; jQuery.fn = jQuery.prototype = { constructor: jQuery, addClass: function(className){ this[0].className += ' ' + className; } }; _jquery.prototype = jQuery.fn; window.$ = window.jQuery = jQuery; })();

 

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

相关文章
  • 7个有用的jQuery小技巧

    7个有用的jQuery小技巧

    2016-02-26 13:02

  • jQuery制作select双向选择列表

    jQuery制作select双向选择列表

    2016-02-26 11:00

  • 全面详细的jQuery常见开发技巧手册

    全面详细的jQuery常见开发技巧手册

    2016-02-26 10:02

  • 强大的jQuery移动插件Top 10

    强大的jQuery移动插件Top 10

    2016-02-25 09:05

网友点评
c