本文翻译自此文章

你有没有遇到过类似$(".cta").click(function(){})这样的JavaScript代码并且在想“$('#x')是什么”?如果这些对你想天书一样,请往下读。如果你认为这些代码不可能是真的,请浏览一些jQuery例子,他们都是这种结构。

这篇文章覆盖了像下面一样吓人的代码片段中涉及的关键概念。我们以一个长例子开始,这个长例子是基于一个让一个正方形运动的简单例子(a simple example of animating a square)。你可能不需要每天做这些,但是这是一个简洁整齐的示范:

$(document).ready(function(){
$("button").click(function(){
$("div").animate({height:"toggle"}).append("hi");
});
});

我们将会涉及到上述例子所用的所有知识点和功能,一窥JavaScript函数,jQuery对象以及事件驱动编程的细节。到了最后,你在面对这种神秘代码时将不会感到困惑。

$什么?

第一眼看,$像是一个特殊的复杂的JavaScript功能。但他不是。在JavaScript中, 美元符号没有特别的含义。事实上,$只是一个函数,他有一个别名jQuery函数

jQuery函数是jQuery库存在的理由(raison d’être of jQuery library)。jQuery是一个消除了不同浏览器之间的JavaScript实现差异的JavaScript库,他还为网页提供了丰富的控制和动画功能。你可以通过引用一份这个库的拷贝来包含jQuery函数(例如,$):

<script src="http://code.jquery.com/jquery-1.11.1.min.js"></script>

或者,你可以下载从官网上一份副本。

jQuery函数通常使用单个参数,不是选择器(selector)就是在页面上的一个JavaScript引用,例如document。选择器是CSS的一部分,在{...}之前。因此,$("div")类似于jQuery("div")。通过选择当前页面上所有的div元素,它的行为十分类似于下面的CSS:

<style>
div {…}
</style>

在我们开始的例子中,$(document)将document这个JavaScript变量传给了jQuery函数。document变量是浏览器自动设置的,它指的是DOM的最顶端。DOM是浏览器自己对页面中的HTML分析后生成的结果,也是jQuery功能的建立基础。例如,jQuery的$("div")十分类似于document.getElementByTagName("div")。

关键点

     要记住,$只是一个函数,他有一个易用的别名叫jQuery函数。

点操作符

     在$(document)后面的.操作符显示了丰富的功能。它和JavaScript对象一起使用。简单的说,JavaScript 是一系列属性的集合。例如:

var digger = new Object();
digger.species = "gerbil";
digger.name = "Digger";
digger.color = "white";

在这个例子中,digger是一个JavaScript对象,我们已经赋给了他三个变量:species、name和color。在面向对象的术语中,他们被叫做成员变量。可以用更简单的方式写:

var digger = {species:"gerbil", name:"Digger", color:"white"};

你也可以赋给对象一个函数作为属性。例如:

function meepMeep(){
alert("meep meep");
}

在JavaScript中,变量、函数和对象之间的界限很模糊。所以,一个函数可以很容易的赋值给一个(成员)变量。

digger.speak = meepMeep;

你可以这样调用函数:

digger.speak();

在面向对象中,这叫做成员函数或者是方法。方法调用同一个对象中的其它方法和成员变量。例如:

function myNameIs(){
alert("Meep! I am a " + this.species);
}
//assign the function
digger.sayMyName = myNameIs;
//call the function
digger.sayMyName();

在myNameIs函数中,特别的变量this指向包含它的对象,this.species等同于digger.species,他们的值是gerbil。如果你试图不通过对象只调用myNameIs函数,this将指向window对象,而this.species将会是window.species,也就是undefined。页面会显示”Meep!I am a undefined.“

对象也可以作为函数的返回值。例如:

function giveMeTheGerbil(){
return digger;
}

他将返回一个(全局)变量或对象digger,就像原来的digger一样。

var digger2 = giveMeTheGerbil();
//alerts "Meep! I am a gerbil"
digger2.sayMyName();

然而,你可以不使用中间变量而直接用giveMeTheGerbil的返回值调用sayMyName:

giveMeTheGerbil().sayMyName();

仔细观察这个代码,它的编程结构和我们最初的例子里的第一行一样:

$(document).ready(…);

下一节将阐述ready函数做什么。

关键点

对象可以简写成{name:"Digger", species:"gerbil"}。The keyword this is used in a function attached to an object (a method) and refers to the containing object.(这句不知该如何翻译)

匿名函数

在JavaScript中有几中创建函数的方法。下满是一种经典的方式(声明式函数),有过编程经验的应该很熟悉:

function meepMeep(){
alert("meep meep");
}

在之前我们已经看到函数可以赋值给变量。我们创建了meepMeep函数并把它赋给了digger.speak。事实上,函数可以被匿名的创建(叫做函数表达式),他没有任何名字并立即赋给一个变量:

var meepMeep = function(){
alert("meep meep");
};

在JavaScript中,函数可以被赋值给变量并像其他变量一样作为实参被传给函数:

function runMe(f){
f();
}

它有一个参数,叫做f。runMe把它当作一个函数并运行他。你可以这样:

runMe(meepMeep);

它将运行meepMeep函数。更有趣的是,你甚至可以不用正式的名字meepMeep。你可以简单的创建他,并立即传递给runMe:

runMe(function(){
alert("meep meep");
});

事实上,任何meepMeep出现的地方,都可以使用等价的匿名函数:

meepMeep();

作为替代,你可以在meepMeep的地方放置一个匿名函数:

(function(){
alert("meep meep");
})();

在JavaScript中,这个技术常用来提供变量作用域。你能明白下面代码要输出什么吗:

var x=3;
(function(){
var x=4; console.log("x is " + x);
})();
console.log ("x is " + x);

在此处,函数中的var关键字很重要。它在函数内声明了一个变量。在此处,匿名函数声明了一个变量x并赋值为4,然后输出它。因为var关键字,函数的x跟之前一行的var x = 3完全的分开了。代码将会先输出x=4然后是x=3。

这里的console.log存在于现代浏览器(换句话,老版IE不支持),他在浏览器的JavaScript控制台输出相关信息。

匿名函数是下一个难题。jQuery的ready函数就像上面runMe函数的有时间延迟的版本。ready函数等待所有的DOM加载完后才执行提供给它的函数。因此,当document最终ready,下面的匿名函数将会执行:

function(){
$("button").click (…)
}

对于程序员来说,要执行那些只能在HTML文档被处理完之后的JavaScript,$(document).ready(...)是一个常用的方法。

关键点

匿名函数是那些没有名字的函数。他们可以赋值给变量,传递给其他函数或者作为立即执行函数来提供作用域。

方法链在更深入例子代码之前,我们需要在复习一次经常发生在JavaScript中的概念。方法链(method chaining)指的是在一行运行多个函数。让我们扩展一下上面giveMeTheGerbil()这个例子:

giveMeTheGerbil().sayMyName();

让我们重新定义一下gerbil相关的函数,让他们返回一个指向自己的引用:

digger.speak = function(){
alert("meep meep"); return this;
}
digger.sayMyName = function(){
alert("Meep! I am a " + this.species); return this;
}

这两个函数对digger做了一些事之后返回digger。这些改变让我们可以链式调用这些函数:

giveMeTheGerbil().speak().sayMyName().speak();

这行代码先运行giveMeTheGerbil,返回一个digger对象引用,现在,这行代码等价于:

digger.speak().sayMyName().speak();

接下来是speak函数,它也返回一个digger对象并在此调用sayMyName函数,一直这样直到最后一个函数。

这样的链式调用在JavaScript非常常见。你可能会见到string对象也有这样的情况。

var s = "I have a dagger.";
console.log(s.substring(9, 15).replace("a", "i").toUpperCase());

上面的代码以字符串s开始,提取子串,用i替换a,是所有字符大写并返回一个在控制台日志显示的字符串。

当然,jQuery中也充斥这链式调用,它也出现在我们的例子里:

$("div").animate({height:"toggle"}).append("hi");

代码首先通过$("div")查询页面中全部的<div>并作为jQuery对象的一部分返回他们。然后,它对jQuery对象运行animate方法接着再运行append方法,每一次返回并操作的都是jQuery对象。

这样的调用链可以非常长,这里有一个特别长的调用链

通常来说,长的调用链会很难调试和维护。避免长调用链始终是个好主意,但在小规模的情况下将非常有用。

关键点

那些返回自身对象引用的方法可以链接在一起,这样就可以在执行长段代码是不用储存中间变量。

jQuery对象

我们例子中使用了几个jQuery方法:ready、click、animate和append。他们都是jQuery对象相关的函数,类似于speak和myNameIs是与digger对象相关的函数,和substr、replace和toUpperCase与string关系一致。

这些函数都是jQuery对象的方法,他们都返回jQuery对象。jQuery对象比digger和string对象都要复杂的多。

之前提过,在JavaScript中,概念之间的界限相当模糊。jQuery对象的行为类似于一个对象和一个数组。你在链式调用时对待他像一个对象,但你也可以对待它象一个数组:

var mydivs = $("div");
for (var i = 0; i < mydivs.length; i++) {console.log(mydivs[i].innerHTML);}

在这个例子中,$("div")查找页面中所有的<div>元素并把生成的jQuery对象存储在mydivs变量中。代码遍历jQuery对象就好像他是DOM中的节点(nodes)数组(实际上,是一个NodeList)。这些节点同样也是包含着各自属性的对象,例如outerHTML和innerHTML。

我们也可以通过把这些节点返回个jQuery对象然后调用jQuery方法html()达到同样的结果。为了实现它,我们把节点传递给$,$可以将任何东西很好的转换为jQuery对象:

var mydivs = $("div");
for (var i = 0; i < mydivs.length; i++) {console.log($(mydivs[i]).html());}

上面两个都可以输出页面中的每个<div>的HTML内容。

记住,当你运行像是$("div").animate(...).append(...)这样的jQuery代码时,动画(animation)将会在jQuery对象中所有的<div>元素中发生,而且他们会作为jQuery对象的一部分传递给下一个在调用链的函数。(对于大多数jQuery函数是这样的,参见这里

关键点

jQuery函数$和许多jQuery方法像click和animate返回一个jQuery对象,jQuery一半类似于对象,一半类似于数组。类型与数组的部分包含着指向在DOM中的节点。

把所有合在一起

现在,我们可以将例子作为一个整体来看了。$(document)返回一个指向页面自己的jQuery对象。ready方法将会在页面完成解析和DOM可用时执行传递给他的方法:

function(){
$("button").click(…);
}

这个函数用jQuery函数查询页面中所有的<buttons>元素。他返回一个有click方法的jQuery对象。click方法中有另一个匿名函数作为参数:

function(){
$("div").animate ({height:"toggle"}).append("hi");
}

这个函数查找全部的<div>元素,返回一个jQuery对象,然后第一个调用它的animate方法。animate方法的参数是用来发生动画的属性列表,这里以简写的对象方式{height:"toggle"}传递给animate。它告诉jQuery切换页面中所有的<div>元素的高度。首先,它(animate方法)减小它们(div元素)的高度至零,然后,它在把它们变回成原来的高度。

animate方法也返回jQuery对象。然后链式调用append方法,这个方法在每次按钮被按下就给<div>元素增加一个字符串"hi"。复制下面代码到JS Bin或创建一个HTML观察:

<button>Click me</button>
<div style="width:100px;height:100px;background:green;"></div>
<script src="http://code.jquery.com/jquery-1.8.3.js"></script>
<script>
$(document).ready(function(){
$("button").click(function(){
$("div").animate({height:"toggle"}).append("hi");
});
});
</script>

每次<button>被点击,绿色的<div>要么被折叠,要么被展开,同时添加一个额外的字符串"hi"。

事件驱动的麻烦

下面一段代码看似很简单:

//set h to 200
var h = 200;
$(document).ready(function(){
$("button").click(function(){
//animate up to h, 200 pixels high
$("div").animate({height:h});
});
});

你可能希望<div>元素扩展到200像素。但是在变量h被赋值为200到动画发生之间可能会出现很多状况。在一个复杂的jQuery应用中,变量h可能会被重用,或者你的应用的其他部分会改变他的值。你将会经盯着那几行代码,并思考到底为什么你的盒子之变换到50像素而不是200像素。可能是在你的代码某个地方你不小心改变了h的值。

老实说,这不是因为jQuery或者是其他匿名函数引起的,但总的来说,这是事件驱动编程的危害。上面的代码运行在三个不同的时间,它们第一次处理($(document).ready(...))。当文档加载($(button).cilck(...))和按钮被点击($("div").animate(...))。

那些例如用PHP写的服务端代码是连续并按照顺序执行的,从开始到结束,输出HTML生成web页面然后结束。JavaScript也可以做这些,但它在和事件联系在一起时,例如按钮点击,它才是最强大的。这就是事件驱动编程,并不只有JavaScript是这样。在智能手机app中大量使用事件驱动,他们使用Object-C 或Java或C++响应你的IPhone,Android或者Windows Phone的触摸屏事件。

如果上面的代码被翻译成Java运行在Android机,在最里层的函数中的h会导致一个错误。这是因为h没有被声明为一个全局(或在Java中是静态变量)变量,内部代码不知道它的值是什么。尽管这没有改变问题,但他至少让你致力于仔细思考如何使用变量。避免这个问题的一个快速方法是给变量加一个作用域。这个例子可以通过在第一个匿名函数中添加一个变量声明 var h 而被修复。这样这个h的优先级将高于任何全局的h。

$(document).ready (function(){
//set h to 200
var h = 200;
$("button").click (function(){
//animate up to h, 200 pixels high
$("div").animate ({height:h});
});
});

如果你必须使用全局配置变量,那另一个技术就是良好的命名并组织变量。同时,清晰的注释终是被推荐的:

//properties of the animation
var animationConfig = {upToHeight:200};
//when document is loaded
$(document).ready(function(){
//when any <button> element is clicked
$("button").click(function(){
//change the height of all <div>s
$("div").animate({height:animationConfig.upToHeight});
});
});

总结

这篇文章是一个关于JavaScript语法和通过jQuery来了解如何使用它的初学者指导。jQuery是一个有着特别长相的函数$和鼓励使用简写的对象,匿名函数和方法链的JavaScript库。不只是jQuery,想YUI(Yahoo User Interface)也是类似的。你现在可以直接看一个复杂的jQuery代码而不会有任何疑问或者不清楚的地方。你知道它是做什么的。由于事件驱动编程的复杂性,你可能不确定是何时做,但你知道是怎么做。

【简译】jQuery对象的奥秘:基础介绍的更多相关文章

  1. JavaScript中如何将html字符串转化为Jquery对象或者Dom对象

    最近在开发百度地图相关的一个应用,需要从硬编码的html字符串中提取自己想要的元素以及属性信息.但是在js中或者jQuery中操作元素节点以及属性都是使用DOM对象或者jquery对象.下面将介绍如何 ...

  2. JavaScript中将html字符串转化为Jquery对象或者Dom对象

    实例代码: $('<a href="javascript:void(0);" onclick="showUI(this,"4028f65d5d1bb627 ...

  3. Jquery学习笔记:事件处理基础介绍

    一.引子 给html的元素添加一个响应事件,最简单的办法是直接在元素标签内填写事件属性,先看一个最简单的例子 <!DOCTYPE html> <html lang="zh- ...

  4. 前端基础进阶(十一):详细图解jQuery对象,以及如何扩展jQuery插件

    早几年学习前端,大家都非常热衷于研究jQuery源码.我还记得当初从jQuery源码中学到一星半点应用技巧的时候常会有一种发自内心的惊叹,“原来JavaScript居然可以这样用!” 虽然随着前端的发 ...

  5. jQuery介绍 DOM对象和jQuery对象的转换与区别

    jQuery介绍 DOM对象和jQuery对象的转换与区别 jQuery介绍      jQuery: http://jquery.com/      write less, do more.   j ...

  6. jQuery对象入门级介绍

    你是否曾经见过像  $(".cta").click(function(){})这样的JavaScrip代码?或许你还会思考下 $('#X') 是什么,如果看到这些你都觉得摸不着头脑 ...

  7. Dom对象和JQuery对象的详细介绍及其区别

    一直搞不清Dom对象和JQuery对象之间的区别,今天好好总结下 1.dom对象(摘抄自百度百科http://baike.baidu.com/link?url=4L8bZ7kW6kE-it4F-1LU ...

  8. jquery对象介绍及一些jquery小特效

    一.jquery对象的介绍. 引入jquery库后,通过形如$("#id")的方式得到的对象叫做jquery对象.如var $uu = $("#username" ...

  9. jQuery编程基础精华01(jQuery简介,顶级对象$,jQuery对象、Dom对象,链式编程,选择器)

    jQuery简介 什么是jQuery? jQuery就是一个JavaScript函数库,没什么特别的.(开源)联想SQLHelper类 jQuery能做什么?jQuery是做什么的? jQuery本身 ...

随机推荐

  1. cmd 连接到指定路径

    cmd 刚刚打开的时候默认路径可能不是自己想要的路径的时候,如何转到自己希望的路径,方法如下: 1.首先敲下想存的硬盘符:D:   2.敲下 cd+文件路径:   总结:其实这次只是简单测试一下上传图 ...

  2. Ext.Net学习笔记05:Ext.Net DirectEvents用法详解

    Ext.Net通过DirectEvents进行服务器端异步的事件处理.我们在 Ext.Net用法概览 这篇中已经简单的介绍了DirectEvents,今天我们将详细的介绍一下DirectEvents. ...

  3. Javascript 数组自定义排序,并获取排序后的保存原索引的同序数组(堆排序实现)

    比如数组A: [ 0: 5, 1: 2, 2: 4, 3: 3, 4: 1 ] 排序后的结果为:[1, 2, 3, 4, 5],但是有时候会有需求想要保留排序前的位置到一个同位数组里,如前例则为:[4 ...

  4. java Email发送及中文乱码处理。

    public class mail { private String pop3Server=""; private String smtpServer=""; ...

  5. 05_天气查询_JAX-WS方式_客户端

    [客户端特点] 支持面向对象开发. 客户端功能调用webService,首先得知道WebService的地址. 一般情况下,只要知道了wsdl的地址,就可以知道WebService的地址. 我们上一篇 ...

  6. zoj 3686 A Simple Tree Problem (线段树)

    Solution: 根据树的遍历道的时间给树的节点编号,记录下进入节点和退出节点的时间.这个时间区间覆盖了这个节点的所有子树,可以当做连续的区间利用线段树进行操作. /* 线段树 */ #pragma ...

  7. [zz]安装Ubuntu 15.10后要做的事

    很有用,收藏 http://blog.csdn.net/skykingf/article/details/45267517

  8. python 自动化之路 day 03

    内容目录: 1. 字典 2. 集合 3. 文件处理 4. 字符编码   1. 字典操作 字典一种key - value 的数据类型,使用就像我们上学用的字典,通过笔划.字母来查对应页的详细内容. 语法 ...

  9. tp_shop解读1

    由于想弄一个商城,因此研究了一下tp_shop,这个据说能完成几乎所有的功能. 考虑到原有的例子过于复杂,因此把所有相关的数据都删除了,结果上来就出错了,查了两天,大致弄清楚了状况. 关于错误的原因 ...

  10. demo_07选择器练习

    <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title&g ...