【简译】jQuery对象的奥秘:基础介绍
本文翻译自此文章
你有没有遇到过类似$(".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对象的奥秘:基础介绍的更多相关文章
- JavaScript中如何将html字符串转化为Jquery对象或者Dom对象
最近在开发百度地图相关的一个应用,需要从硬编码的html字符串中提取自己想要的元素以及属性信息.但是在js中或者jQuery中操作元素节点以及属性都是使用DOM对象或者jquery对象.下面将介绍如何 ...
- JavaScript中将html字符串转化为Jquery对象或者Dom对象
实例代码: $('<a href="javascript:void(0);" onclick="showUI(this,"4028f65d5d1bb627 ...
- Jquery学习笔记:事件处理基础介绍
一.引子 给html的元素添加一个响应事件,最简单的办法是直接在元素标签内填写事件属性,先看一个最简单的例子 <!DOCTYPE html> <html lang="zh- ...
- 前端基础进阶(十一):详细图解jQuery对象,以及如何扩展jQuery插件
早几年学习前端,大家都非常热衷于研究jQuery源码.我还记得当初从jQuery源码中学到一星半点应用技巧的时候常会有一种发自内心的惊叹,“原来JavaScript居然可以这样用!” 虽然随着前端的发 ...
- jQuery介绍 DOM对象和jQuery对象的转换与区别
jQuery介绍 DOM对象和jQuery对象的转换与区别 jQuery介绍 jQuery: http://jquery.com/ write less, do more. j ...
- jQuery对象入门级介绍
你是否曾经见过像 $(".cta").click(function(){})这样的JavaScrip代码?或许你还会思考下 $('#X') 是什么,如果看到这些你都觉得摸不着头脑 ...
- Dom对象和JQuery对象的详细介绍及其区别
一直搞不清Dom对象和JQuery对象之间的区别,今天好好总结下 1.dom对象(摘抄自百度百科http://baike.baidu.com/link?url=4L8bZ7kW6kE-it4F-1LU ...
- jquery对象介绍及一些jquery小特效
一.jquery对象的介绍. 引入jquery库后,通过形如$("#id")的方式得到的对象叫做jquery对象.如var $uu = $("#username" ...
- jQuery编程基础精华01(jQuery简介,顶级对象$,jQuery对象、Dom对象,链式编程,选择器)
jQuery简介 什么是jQuery? jQuery就是一个JavaScript函数库,没什么特别的.(开源)联想SQLHelper类 jQuery能做什么?jQuery是做什么的? jQuery本身 ...
随机推荐
- 理解Objective-c中的copy
说一下深拷贝和浅拷贝的基本概念:a指针指向地址A1, 浅拷贝是创建了一个b指针指向地址A1:深拷贝是创建了一个c指针指向地址A2,A1和A2的地址不同. 我们看到NSObject接口里面是已经声明了c ...
- Lua Script
注意事项: 1:Lua 只支持数字类型,浮点类型的值,在转换成Redis 协议值得时候,小数点会被忽略(如果需要在Lua中使用浮点值,建议用字符串代替) 2:Lua 返回表中如果遇到nils(空),转 ...
- Oracle初始化
/*第1步:创建临时表空间 */ create temporary tablespace mdb_temp tempfile 'G:\data\oracle\mdb_temp.ora' size 10 ...
- C语言之指针1.1数组
void main() { ]={,,,,,}; ;i++) { printf("%d\n",*(arr+i)); } } 输出结果时候123456
- OC 消息传递机制
消息传递(message passing)的概念是Smalltalk语言的核心原则之一,有时Smalltalk和Objective-C被称为面向消息的语言,通常“消息”一词的含义和“方法”是相同的. ...
- STL中map与hash_map的比较
1. map : C++的STL中map是使用树来做查找算法; 时间复杂度:O(log2N) 2. hash_map : 使用hash表来排列配对,hash表是使用关键字来计算表位置; 时间复杂度:O ...
- (转)linux多线程,线程的分离与结合
转自:http://www.cnblogs.com/mydomain/archive/2011/08/14/2138454.htm 线程的分离与结合 在任何一个时间点上,线程是可结合的(joi ...
- jQuery查看dom元素上绑定的事件列表
jQuery API提供了一种能够查看元素已绑定事件的列表,这个功能在进行功能调试的时候特别有用,尤其确定在代码执行过程中元素绑定的事件是否被更改. 1: jQuery( elem ).dat ...
- linux根目录详解
ubuntu 文件说明:http://tech.ccidnet.com/art/302/20080118/1347213_1.html/ 根目录 | |-boot/ 启动文件.所有与系统启动有关的 ...
- 在 Linux 命令行中使用和执行 PHP 代码
PHP是一个开源服务器端脚本语言,最初这三个字母代表的是“Personal Home Page”,而现在则代表的是“PHP:Hypertext Preprocessor”,它是个递归首字母缩写.它是一 ...