你是否曾经见过像 $(".cta").click(function(){})
这样的JavaScrip代码?或许你还会思考下 $('#X')
是什么,如果看到这些你都觉得摸不着头脑,那请一定要读完这篇文章。如果你觉得上述的代码片段是不能正常工作的,那请先看一些jQuery的代码范例,你会发现链接中的代码都是这样的结构。
这篇文章将会分析下面代码片段(动画化一个方形)中出现的一些关键知识点。你可能不会经常接触这样的代码,但了解一下这段代码的机制有助于你理解jQuery:
1 2 3 4 5 |
$(document).ready(function(){ $("button").click(function(){ $("div").animate({height:"toggle"}).append("hi"); }); }); |
我们将会逐字逐句地解释上述的代码,告诉你JavaScript函数、jQuery对象还有事件驱动编程的具体细节。希望看完这篇文章以后,再遇到神秘的jQuery代码时你不会再头疼。
$是什么?
在你第一眼看到$的时候,有一种高大上的猜测在你心中盘旋:这一定是个很特别很复杂的JS方法。事实上,它很普通,也没有什么特殊的含义。$就是一个函数,是jQuery函数的另一个名字罢了。
jQuery是一个比较简单的JavaScript库,它在浏览器兼容方面做得很好,而且还提供了许多很有用的特性用来操作网页或者做些动画效果。你可以先引入jQuery库的地址,然后就能使用jQuery函数(比如$)了:
1 |
<script src="http://code.jquery.com/jquery-1.11.1.min.js"></script> |
或者你也可以直接在jQuery官网上下载它。
jQuery函数通常只需要一个参数,这个参数可以是一个选择器也可以是JS引用页面上的内容(比如document)。
选择器就是CSS的一个片段,写在{…}之前的内容就是选择器了。所以,$(“div”)和jQuery(“div”)是一个意思,就是简单粗暴地把页面上所有的<div>标签都选中,和在CSS中使用.div获得的是同一个结果。
1 2 3 |
<style> div {…} </style> |
还记得在代码的最开头有一个$(document)吗?这一步是要把JS变量document传入jQuery方法当中。document是由浏览器来定义的,可以直接使用,它指的是文档对象模型(DOM)的最顶层。DOM指的是各个浏览器是如何来解释页面的整个HTML结构。用jQuery写的程序是基于DOM的。jQuery中的$(‘div’)和document.getElementsByTagNae(“div”)得到的结果大致上是一样的。
关键点
$只是一个方法,它是jQuery方法的简写也是它另一个名字。
点
在$(document)之后的点(’.’)预示着有许多方法可以被调用。一定要是一个JS对象才能使用这个点。说个最简单的,一个JS对象就是一堆属性的集合:
1 2 3 4 |
var digger = new Object(); digger.species = "gerbil"; digger.name = "Digger"; digger.color = "white"; |
上面代码中,变量digger是一个对象,我们赋值了三个子对象给它:species,name和color。在面向对象编程中,这三个变量被称为成员变量。你可能更简洁地写成这样:
1 |
var digger = {species:"gerbil", name:"Digger", color:"white"}; |
你也可以把方法当做属性赋值给一个变量。沙鼠(Gerbil)大部分时候都很安静,但他们偶尔也会发出高频meeping sort of noise。在JS中,可以这么来表示:
1 2 3 |
function meepMeep(){ alert("meep meep"); } |
在JS中,变量、方法和对象之间的界限是很模糊的,所以一个方法也可以被赋值到一个(成员)变量上:
1 |
digger.speak = meepMeep; |
现在你可一个调用这个方法来让沙鼠发出叫声来:
1 |
digger.speak(); |
在面向对象语法中,digger.speak();是一个成员方法或者函数。在同一个对象中的方法可以互相引用,它们还能引用其他的成员变量。想象一下Digger学会了说英语,这得是多牛X的一件事啊:
1 2 3 4 5 6 7 |
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指的就是JS的window对象,this.species就是window.species,,在这里它的值是undefined。页面的弹框中的文字会变成”Meep! I am a undefined”。
对象也可以作为函数的返回值,我个人也推荐这么使用:
1 2 3 |
function giveMeTheGerbil(){ return digger; } |
这么写的话,返回的就是(全局)变量/对象digger的引用,它和最初的digger是完全一样的,所以操作它的时候你不需要有什么顾虑。
1 2 3 |
var digger2 = giveMeTheGerbil(); //alerts "Meep! I am a gerbil" digger2.sayMyName(); |
你也可以不通过digger2这个中间值,而是直接在giveMeTheGerbil的返回值上调用sayMayName:
1 |
giveMeTheGerbil().sayMyName(); |
先不考虑内部代码,这种程序结构和例子里第一行代码是一样的:
1 |
$(document).ready(…); |
下一节你将知道ready的作用是什么。
关键点
将对象简写:{name:”Digger”, species:”gerbil”},在方法中使用到的this是依附于一个对象(或者一个方法)的,它指向包含它的对象。
匿名函数
在JS中,创建函数的方法多种多样。只要你有一点编程经验那对下面的函数声明就不会陌生:
1 2 3 |
function meepMeep(){ alert("meep meep"); } |
在上文里我们已经知道了函数是可以被赋值到变量上的。我们创建了meepMeep函数,并将它赋值到digger.speak上。事实上,函数还可以被匿名地创建出来(我们称呼这样的函数为:函数表达式),它们在声明时是没有任何名字的,声明后再被赋值到一个变量上:
1 2 3 |
var meepMeep = function(){ alert("meep meep"); }; |
在JS中,函数可以被赋值到变量上,还能像变量一样到处传递。让我们看看下面这个例子:
1 2 3 |
function runMe(f){ f(); } |
runMe函数有一个传入参数f,它将这个传入参数视作一个函数,还调用的这个函数。所以你可以这么使用runMe:
1 2 3 |
runMe(function(){ alert("meep meep"); }); |
这样meepMeep函数就会被成功调用。如果在这个方法里,你连meepMeep的名字都不需要了,那事情就会更有趣些了。你可以直接创建它,当需要的时候再把它传入runMe来调用这个函数:
1 |
meepMeep(); |
事实上,哪里都会出现meepMeep,等同于它的匿名函数也是这样的。这么调用: