<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>10V &#187; javascript</title>
	<atom:link href="http://www.smartwei.com/category/javascript/feed" rel="self" type="application/rss+xml" />
	<link>http://www.smartwei.com</link>
	<description>干一行，爱一行</description>
	<lastBuildDate>Fri, 13 Jan 2012 01:22:37 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Firebug &amp; Chrome Console 控制台使用指南</title>
		<link>http://www.smartwei.com/firebug-chrome-console-guid.html</link>
		<comments>http://www.smartwei.com/firebug-chrome-console-guid.html#comments</comments>
		<pubDate>Wed, 23 Mar 2011 16:48:18 +0000</pubDate>
		<dc:creator>10V</dc:creator>
				<category><![CDATA[javascript]]></category>
		<category><![CDATA[常用工具]]></category>
		<category><![CDATA[firebug]]></category>

		<guid isPermaLink="false">http://www.smartwei.com/?p=312</guid>
		<description><![CDATA[本文介绍了如何使用firebug的console（控制台）来调试javascript]]></description>
			<content:encoded><![CDATA[<div style="font: bold 18px Arial;color: #C00;margin-top:20px">Console API</div>
<p>当打开 firebug (也包括 Chrome 等浏览器的自带调试工具)，window 下面会注册一个叫做 console 的对象，它提供多种方法向控制台输出信息，供开发人员调试使用。下面是这些方法的一个简单介绍，适时地运用它们，对于提高开发效率很有帮助。</p>
<p><strong>console.log(object[, object, ...])</strong><br />
使用频率最高的一条语句：向控制台输出一条消息。支持 C 语言 printf 式的格式化输出。当然，也可以不使用格式化输出来达到同样的目的：</p>
<pre lang="javascript">
var animal='frog', count=10;
console.log("The %s jumped over %d tall buildings", animal, count);
console.log("The", animal, "jumped over", count, "tall buildings");
</pre>
<p><strong>console.debug(object[, object, ...])</strong><br />
向控制台输出一条信息，它包括一个指向该行代码位置的超链接。</p>
<p><strong>console.info(object[, object, ...])</strong><br />
向控制台输出一条信息，该信息包含一个表示“信息”的图标，和指向该行代码位置的超链接。</p>
<p><strong>console.warn(object[, object, ...])</strong><br />
同 info。区别是图标与样式不同。</p>
<p><strong>console.error(object[, object, ...])</strong><br />
同 info。区别是图标与样式不同。error 实际上和 throw new Error() 产生的效果相同，使用该语句时会向浏览器抛出一个 js 异常。</p>
<p><strong>console.assert(expression[, object, ...])</strong><br />
断言，测试一条表达式是否为真，不为真时将抛出异常（断言失败）。</p>
<p><strong>console.dir(object)</strong><br />
输出一个对象的全部属性（输出结果类似于 DOM 面板中的样式）。</p>
<p><strong>console.dirxml(node)</strong><br />
输出一个 HTML 或者 XML 元素的结构树，点击结构树上面的节点进入到 HTML 面板。</p>
<p><strong>console.trace()</strong><br />
输出 Javascript 执行时的堆栈追踪。</p>
<p><strong>console.group(object[, object, ...])</strong><br />
输出消息的同时打开一个嵌套块，用以缩进输出的内容。调用 console.groupEnd() 用以结束这个块的输出。</p>
<p><strong>console.groupCollapsed()</strong><br />
同 console.group(); 区别在于嵌套块默认是收起的。</p>
<p><strong>console.time(name)</strong><br />
计时器，当调用 console.timeEnd(name);并传递相同的 name 为参数时，计时停止，并输出执行两条语句之间代码所消耗的时间（毫秒）。</p>
<p><strong>console.profile([title])</strong><br />
与 profileEnd() 结合使用，用来做性能测试，与 console 面板上 profile 按钮的功能完全相同。</p>
<p><strong>console.count([title])</strong><br />
输出该行代码被执行的次数，参数 title 将在输出时作为输出结果的前缀使用。</p>
<p><strong>console.clear()</strong><br />
清空控制台</p>
<div style="font: bold 18px Arial;color: #C00;margin-top:20px">命令行</div>
<p>控制台的输出面板右边，是控制台的输入面板（Chrome 调试工具对应为下方），在这里除了可以运行常规的 javascript 代码，还内置了相当数量的命令行可以辅助我们的调试工作，下面是一些常用命令行的简单介绍。</p>
<p><strong>$(id)</strong><br />
返回一个给定 id 的元素。</p>
<p><strong>$$(selector)</strong><br />
返回给定的 css 选择器匹配到的一组元素。</p>
<p><strong>$x(xpath)</strong><br />
返回给定的 XPath 表达式匹配到的一组元素。</p>
<p><strong>$0</strong><br />
在 HTML 面板中选中的元素。</p>
<p><strong>$1</strong><br />
上一次在 HTML 面板中选中的元素。</p>
<p><strong>$n(index)</strong><br />
访问最近 5 个被选中过的元素，index 的范围： 0 &#8211; 4。</p>
<p><strong>dir(object)</strong><br />
同 console.dir(object)。</p>
<p><strong>dirxml(node)</strong><br />
同 console.dirxml(node)。</p>
<p><strong>clear()</strong><br />
同 console.clear()。</p>
<p><strong>inspect(object[, tabName])()</strong><br />
在合适的（或一个指定的） tab 中检视一个对象。</p>
<p><strong>keys(object)</strong><br />
返回一个对象的所有属性的键。</p>
<p><strong>values(object)</strong><br />
返回一个对象的所有属性的值。</p>
<p><strong>debug(fn)</strong><br />
在函数第一行添加一个断点，使用 undebug(fn) 移除断点。</p>
<p><strong>monitor(fn)</strong><br />
开启一个函数的调用日志，使用 unmonitor(fn) 关闭该功能。非常有用的一个命令，但是它似乎并没有很好地工作。</p>
<p><strong>monitorEvents(object[, types])</strong><br />
开启一个元素的某个事件（或所有事件）被触发时的日志记录。用例如下：</p>
<pre lang="javascript">
monitorEvents($0,['click'])
</pre>
<p>上面的命令行被执行后，将开启当前在 HTML 面板中被选中元素的 click 事件监控，一旦这个元素的 click 事件被触发，事件对象将会在控制台输出。如果不指定第二个参数，将对所有事件进行记录。</p>
<p><strong>profile([title])</strong><br />
同 console.profile([title])</p>
]]></content:encoded>
			<wfw:commentRss>http://www.smartwei.com/firebug-chrome-console-guid.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>《javascript精粹》读书笔记 – 数组</title>
		<link>http://www.smartwei.com/%e3%80%8ajavascript%e7%b2%be%e7%b2%b9%e3%80%8b%e8%af%bb%e4%b9%a6%e7%ac%94%e8%ae%b0-%e6%95%b0%e7%bb%84.html</link>
		<comments>http://www.smartwei.com/%e3%80%8ajavascript%e7%b2%be%e7%b2%b9%e3%80%8b%e8%af%bb%e4%b9%a6%e7%ac%94%e8%ae%b0-%e6%95%b0%e7%bb%84.html#comments</comments>
		<pubDate>Sun, 23 Jan 2011 15:27:24 +0000</pubDate>
		<dc:creator>10V</dc:creator>
				<category><![CDATA[javascript]]></category>
		<category><![CDATA[javascript精萃]]></category>

		<guid isPermaLink="false">http://www.smartwei.com/?p=309</guid>
		<description><![CDATA[记录《javascript精粹》中“数组”这一章节的知识点]]></description>
			<content:encoded><![CDATA[<p><strong>1. </strong>数组length属性的值是这个数组的最大整数属性名加上1.它不一定等于数组里属性的个数：<br />
[js]<br />
var myArray = [];<br />
alert(myArray.length); // 0</p>
<p>myArray[1000000] = true;<br />
alert(myArray.length); //1000001<br />
[/js]</p>
<p><strong>2. </strong>在数组尾部添加一个新元素：<br />
[js]<br />
var numbers = ['zero', 'one', 'two'];<br />
numbers[numbers.length] = &#8216;three&#8217;;<br />
numbers.push(&#8216;four&#8217;);<br />
[/js]</p>
<p><strong>3. </strong>删除数组元素。<br />
js中的数组实际上就是对象，所以delete运算符就可以用来从数组中移除元素：<br />
[js]<br />
var numbers = ['one', 'two', 'three', 'four'];<br />
delete numbers[2]; // ['one', 'two', undefined, 'four']<br />
[/js]<br />
不幸的是，那样会在数组中遗留一个空洞。 通常可以使用splice方法来删除元素：<br />
[js]<br />
var numbers = ['one', 'two', 'three', 'four'];<br />
numbers.splice(2, 1); //['one', 'two', 'four']<br />
[/js]<br />
这个对大型数组来说可能会效率不高。</p>
<p><strong>4. </strong>当属性名是小而连续的整数时，应该使用数组；否则使用对象。</p>
<p>5. 判断是否是数组：<br />
[js]<br />
var is_array = function(value){<br />
	return value &amp;&amp;<br />
		typeof value === &#8216;object&#8217; &amp;&amp;<br />
		value.constructor === Array;<br />
};<br />
[/js]<br />
不幸的是，它在识别从不同的窗口(window)或帧(frame)里构造的数组时会失败。完整的测试方法如下：<br />
[js]<br />
var is_array = function(value){<br />
	return value &amp;&amp;<br />
		typeof value === &#8216;object&#8217; &amp;&amp;<br />
		typeof value.length === &#8216;number&#8217; &amp;&amp;<br />
		typeof value.splice === &#8216;function&#8217; &amp;&amp;<br />
		!(value.propertyIsEnumberable(&#8216;length&#8217;));<br />
};<br />
[/js]</p>
]]></content:encoded>
			<wfw:commentRss>http://www.smartwei.com/%e3%80%8ajavascript%e7%b2%be%e7%b2%b9%e3%80%8b%e8%af%bb%e4%b9%a6%e7%ac%94%e8%ae%b0-%e6%95%b0%e7%bb%84.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>《javascript精粹》读书笔记 – 函数</title>
		<link>http://www.smartwei.com/javascript-good-part-note-function.html</link>
		<comments>http://www.smartwei.com/javascript-good-part-note-function.html#comments</comments>
		<pubDate>Fri, 14 Jan 2011 01:49:19 +0000</pubDate>
		<dc:creator>10V</dc:creator>
				<category><![CDATA[javascript]]></category>
		<category><![CDATA[javascript 闭包]]></category>
		<category><![CDATA[javascript精萃]]></category>

		<guid isPermaLink="false">http://www.smartwei.com/?p=305</guid>
		<description><![CDATA[记录《javascript精粹》中“函数”这一章节的知识点]]></description>
			<content:encoded><![CDATA[<p>1. 当实际参数的个数与形式参数的个数不匹配时，不会导致错误。<br />
如果实际参数值过多了，超出的参数值将被忽略；如果实际的参数值过少，缺失的值将被替换为undefined。</p>
<p>2. 在javascript中一共有四种调用模式： 方法调用模式、函数调用模式、构造器调用模式和apply调用模式。这些模式在如何初始化关键参数this上存在差异。<br />
a.方法调用模式：<br />
当一个函数被保存为对象的一个属性时，我们称它为一个方法。方法调用模式可以使用this去访问对象，所以它能够从对象中取值或修改对象。<br />
b.函数调用模式：<br />
当一个函数并非一个对象的属性时，它被当作一个函数来调用。当函数以此模式调用时，this被绑定到全局变量，这是语言设计上的一个错误。（正确的情况：当内部函数被调用时，this应该仍然被绑定到外部函数的this变量。）解决方法：如果该方法定义一个变量并给他赋值为this,那么内部函数就可以通过那个变量访问到this,按照约定，给那个变量命名为 that：<br />
[js]<br />
	//给 myObject增加一个double方法<br />
	myObject.double = function()<br />
	{<br />
		var that = this; //解决方法</p>
<p>		var helper = function()<br />
		{<br />
			that.value = add(that.value, that.value);<br />
		}</p>
<p>		helper(); //以函数的形式调用helper。<br />
	}</p>
<p>	//以方法的形式调用double<br />
	myObject.double();<br />
[/js]<br />
c.构造器调用模式：<br />
在一个函数前面带上new来调用，那么将创建一个隐藏连接到该函数的prototype成员的新对象，同时this将会被绑定到那个新对象上。<br />
[js]<br />
	//创建一个名为Quo的构造函数。它构造一个带有status属性的对象<br />
	var Quo = function(String)<br />
	{<br />
		this.status = String;<br />
	}</p>
<p>	//给Quo的所有实例提供一个名为get_status的公共方法<br />
	Quo.prototype.get_status = function()<br />
	{<br />
		return this.status;<br />
	}</p>
<p>	//构造一个Quo实例<br />
	var myQuo = new Quo(&quot;confused&quot;); //构造器模式调用<br />
	document.writeln(myQuo.get_status());<br />
[/js]<br />
按照约定，构造器函数保存在以大写格式命名的变量里。<br />
d.Apply调用模式:<br />
apply方法接受两个参数，第一个是将被绑定给this的值，第二个就是参数数组。它让我们构建一个参数数组并用其去调用函数。<br />
[js]<br />
	//构造一个Quo实例<br />
	var myQuo = new Quo(&quot;confused&quot;); //构造器模式调用<br />
	document.writeln(myQuo.get_status());</p>
<p>	//构建一个包含两个数字的数组，并将他们相加<br />
	add = function(a, b)<br />
	{<br />
		return a+b;<br />
	}</p>
<p>	var anArray = [3, 4];<br />
	var sum = add.apply(null, anArray);  //7</p>
<p>	//构建一个包含status成员的对象<br />
	var statusObject = {<br />
		status: &quot;A-OK&quot;<br />
	};</p>
<p>	//statusObject并没有继承自Quo.prototype,但我们可以再statusObject上调用<br />
	//get_status方法，尽管statusObject并没有一个名为get_status的方法。<br />
	var status = Quo.prototype.get_status.apply(statusObject);<br />
[/js]</p>
<p>3. 参数：<br />
当一个函数被调用时，会有一个默认的参数，就是 arguments “数组”。<br />
[js]<br />
	//构造一个将很多值相加的函数</p>
<p>	//注意该函数内部定义的变量sum不会与函数外部定义的sum产生冲突。<br />
	//该函数只能看到内部的那个变量。<br />
	var sum = function()<br />
	{<br />
		var i, sum=0;<br />
		for(i = 0; i &lt; arguments.length; i+=1)<br />
		{<br />
			sum += arguments[i];<br />
		}<br />
		return sum;<br />
	};</p>
<p>	document.writeln(sum(4, 8, 15, 16, 23, 42)); //108<br />
[/js]<br />
注：arguments并不是一个真正的数组。它知识一个“类似数组”的对象。arguments用友一个length属性，但它缺少所有的数组方法。</p>
<p>4. 返回:<br />
一个函数总是会返回一个值。如果没有置顶返回值，则返回undefined。<br />
如果函数以构造器方式被调用，且返回值不是一个对象，则返回this(该新对象)。</p>
<p>5.给类型增加方法：<br />
[js]<br />
	Function.prototype.method = function(name, func)<br />
	{<br />
		this.prototype[name] = func;<br />
		return this;<br />
	}</p>
<p>	//给Number添加一个integer方法，来提取数字钟的整数部分<br />
	//根据正负来判断是使用Math.ceil还是Math.floor<br />
	Number.method(&#8216;integer&#8217;, function(){<br />
	 return Math[this &lt; 0 ? 'ceil' : 'floor'](this);<br />
	});</p>
<p>	document.writeln((-10/3).integer()); //-3</p>
<p>	//去掉字符串两端空白的方法<br />
	String.method(&#8216;trim&#8217;, function()<br />
	{<br />
		return this.replace(/^\s+|\s+$/g, ”);<br />
	});<br />
[/js]<br />
基本类型的原型是公共结构，所以在类库混用时务必小心。一个保险的做法就是只在确定没有该方法时再添加：<br />
[js]<br />
	//有条件的增加一个方法</p>
<p>	Function.prototype.method = function(name, func)<br />
	{<br />
		if(!this.prototype[name])<br />
		{<br />
			this.prototype[name] = func;<br />
			return this;<br />
		}<br />
	};<br />
[/js]</p>
<p>6.闭包<br />
理解内部函数能访问外部函数的实际变量而无需<strong>复制</strong><br />
[js]<br />
//构造一个函数，用错误的方式给一个数组中的借点设置事件处理程序<br />
//当点击一个节点时，按照预想应该弹出一个对话框显示节点的序号<br />
//但他总是会显示节点的数目</p>
<p>var add_the_handlers = function(nodes) {<br />
	var i;<br />
	for (i = 0; i &lt; nodes.length; i += 1) {<br />
			nodes[i].onclick = function(e) {<br />
				alert(i);<br />
			}<br />
	}<br />
}<br />
[/js]<br />
add_the_handlers函数的目的是给每个事件处理器一个唯一值（i）。它未能达到目的的原因是事件处理器函数绑定了变量i，而不是<strong>函数在构造时的变量i的值</strong>。<br />
正确的写法：<br />
[js]<br />
//点击一个节点，将会弹出一个对话框显示节点的序号<br />
var add_the_handlers = function (nodes) {<br />
	var i;<br />
	for (i = 0; i &lt; nodes.length; i +=1 ) {<br />
		nodes[i].onclick = function (i) {<br />
			return funtion (e) {<br />
				return alert(e);<br />
			} ;<br />
		}(i);<br />
	}<br />
}<br />
[/js]<br />
现在，定义了一个函数并立即传递i进去执行， 而不是把一个函数赋值给onclick。那个函数将返回一个事件处理器函数。这个事件处理器函数绑定的是传递进去的i的值，而不只定义在add_the_handlers函数里的i的值。那个被返回的函数被复制给onclick。</p>
<p>7.javascript的单例模式<br />
Javascript的单例就是用对象字面量表示法创建的对象，对象的属性值可以是数值或函数，并且属性值在该对象的生命周期中不会发生变化。他通常作为<b>工具为程序其他部分提供功能支持</b></p>
<p>8.模块<br />
模块模式的一般形式是：一个定义了<b>私有变量和函数的函数</b>；利用<b>闭包</b>创建可以访问<b>私有变量和函数</b>的特权函数,或者把他们保存到一个可访问的地方。<br />
[js]<br />
String.method(&#8216;deentityify&#8217;, function (){<br />
	var entity = {<br />
		quot: &#8216;&quot;&#8217;,<br />
		lt: &#8216;&lt;&#8217;,<br />
		gt: &#8216;&gt;&#8217;<br />
	}</p>
<p>	return function () {<br />
		return this.replace(/&amp;([^&amp;;]+);/g,<br />
			function (a, b) {<br />
				var r = entity[b];<br />
				return typeof r === &#8216;string&#8217; ? r : a;<br />
		});<br />
	};<br />
}());<br />
[/js]<br />
模块模式利用了函数作用域和闭包来创建绑定对象与私有成员关联，摒弃了全局变量的使用，从而缓解这个JavaScript的最为糟糕的特性之一所带来的影响</p>
]]></content:encoded>
			<wfw:commentRss>http://www.smartwei.com/javascript-good-part-note-function.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>《javascript精粹》读书笔记 &#8211; 对象</title>
		<link>http://www.smartwei.com/javascript-good-part-note.html</link>
		<comments>http://www.smartwei.com/javascript-good-part-note.html#comments</comments>
		<pubDate>Sun, 09 Jan 2011 05:29:33 +0000</pubDate>
		<dc:creator>10V</dc:creator>
				<category><![CDATA[javascript]]></category>
		<category><![CDATA[javascript精萃]]></category>

		<guid isPermaLink="false">http://www.smartwei.com/?p=302</guid>
		<description><![CDATA[整理了《javascript精粹》中关于对象的一些内容]]></description>
			<content:encoded><![CDATA[<p>《javascript精粹》中和对象相关的内容：</p>
<p>1. 当尝试检索对象的一个并不存在的成员元素的值，将返回一个undefined值。可以通过“||”运算符来填充默认值：<br />
[js]<br />
stooge[&quot;middle-name&quot;] //undefined<br />
var middle = stooge[&quot;middle-name&quot;] || &quot;tom&quot;;<br />
[/js]</p>
<p>2. 当尝试检索一个undefined值将会导致TypeError异常。可以通过“&#038;&#038;”运算符来避免错误：<br />
[js]<br />
flight.equipment  //undefined<br />
flight.equipment.model //throw &quot;TypeError&quot;<br />
flight.equipment &amp;&amp; flight.equipment.model //undefined<br />
[/js]</p>
<p>3. 对象通过引用来传递。他们永远不会被拷贝<br />
[js]<br />
var x = stooge;<br />
x.nickname = &#8216;Curly&#8217;;<br />
var nick = stooge.nickname;<br />
//因为x和stooge是指向同一个对象的引用，所以nick的值为&#8217;Curly&#8217;</p>
<p>var a={}, b={}, c={};<br />
//a, b和c每个都引用一个&lt;strong&gt;不同&lt;/strong&gt;的空对象</p>
<p>a=b=c={}<br />
//a,b和c都引用&lt;strong&gt;同一个&lt;/strong&gt;空对象<br />
[/js]</p>
<p>4. 原型连接<br />
通过beget方法创建一个使用原对象作为其原型的新对象<br />
[js]<br />
if (typeof Object.beget !== &#8216;function&#8217;)<br />
{<br />
    Object.beget = function (o)<br />
    {<br />
        var F = function () {};<br />
        F.prototype = o;<br />
        return new F();<br />
    }<br />
}</p>
<p>var another_stooge = Object.beget(stooge);<br />
[/js]<br />
<strong>注：</strong><br />
a. 原型连接在更新时是不起作用的<br />
当我们对某个对象作出改变时，不会触及到该对象的原型。<br />
b. 原型连接只有在检索值的时候才被用到<br />
如果尝试去获取对象的某个属性值，且该对象没有此属性名，那么从它的圆形对象中获取属性值。 （如果那个原型对象也没有该属性值，那么再从它的原型中寻找，依次类推，知道该过程左后的重点Object.prototype。如果想要的属性完全不存在于原型链中，那么结果就是<strong>undefined</strong>值。这个过程称为<strong>委托</strong>）<br />
c. 原型关系是一种动态关系。<br />
如果我们添加一个新的属性到原型中，该属性会立即对所有基于该原形创建的对象可见。</p>
<p>5. 反射<br />
在一些时候下，我们需要能够在对对象完全不了解的情况下进行处理，并且在处理之前发现他们的属性和方法，这个过程称作反射（reflection）。<br />
在判断对象是否有某一属性时，可以使用”<strong>hasOwnProperty</strong>“方法，如果对象拥有独有的属性，它将返回true。<br />
注：hasOwnProperty方法不会检查原型链。</p>
<p>6. 枚举<br />
for in 语句可以用来遍历一个对象中的所有属性名。<br />
属性名出现的顺序是不确定的，因此要对任何可能出现的顺序有所准备。如果你想要确保属性以特定的顺序出现，最好的办法就是完全避免使用for in语句，而是创建一个数组，在其中以正确的顺序包含属性名：<br />
[js]<br />
//使用for in语句：<br />
	var name;<br />
	for (name in another_stooge)<br />
	{<br />
		if(typeof another_stooge[name] !== &#8216;function&#8217;)<br />
		{<br />
			document.writeln(name + &#8216;: &#8216; + another_stooge[name]);<br />
		}<br />
	}</p>
<p>//使用for语句<br />
	var i;<br />
	var properties = [<br />
		'first-name',<br />
		'middle-name',<br />
		'last-name',<br />
		'profession'<br />
	]<br />
	for (i=0; i&lt;properties.length; i +=1)<br />
	{<br />
		document.writeln(properties[i] + &#8216;: &#8216; +<br />
					another_stooge[properties[i]]);<br />
	}<br />
[/js]</p>
]]></content:encoded>
			<wfw:commentRss>http://www.smartwei.com/javascript-good-part-note.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>js DOM 事件绑定</title>
		<link>http://www.smartwei.com/js-add-event.html</link>
		<comments>http://www.smartwei.com/js-add-event.html#comments</comments>
		<pubDate>Thu, 11 Nov 2010 03:45:46 +0000</pubDate>
		<dc:creator>10V</dc:creator>
				<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://www.smartwei.com/?p=288</guid>
		<description><![CDATA[jsDOM事件绑定以及onload事件绑定——兼容原有函数]]></description>
			<content:encoded><![CDATA[<p><b>Js绑定DOM事件</b><br />
[js]<br />
function addEvent( obj, type, fn ) {<br />
	if( obj.attachEvent ) {<br />
		obj[ 'e' + type + fn ] = fn;<br />
		obj[ type + fn ] = function() {<br />
			ojb[ 'e' + type + fn ]( window.event );<br />
		}<br />
		obj.attachEvent( &#8216;on&#8217; + type, obj[ type + fn ]);<br />
	}<br />
	else {<br />
		obj.addEventListener( type, fn, false );<br />
	}<br />
}</p>
<p>function removeEvent( ojb, type, fn ) {<br />
	if( obj.detachEvent ) {<br />
		obj.detachEvent( &#8216;on&#8217; + type + obj[ type + fn ] );<br />
		obj[ type + fn ] = null;<br />
	}<br />
	else {<br />
		ojb.removeEventListener( type, fn, false );<br />
	}<br />
}<br />
[/js]<br />
<br />
<b>JS绑定onLoad事件</b><br />
[js]<br />
function addLoadEvent( func ) {<br />
	var oldonload = window.onload;<br />
	if( typeof window.onload != &#8216;function&#8217; ) {<br />
		window.onload = func;<br />
	}<br />
	else {<br />
		window.onload = function() {<br />
			oldonload();<br />
			func();<br />
		}<br />
	}<br />
}<br />
[/js]<br />
作者: <a href="http://www.smartwei.com">石巍</a><br />
原载: <a href="http://www.smartwei.com/js-add-event.html">10V的博客</a><br />
链接: <a href="http://www.smartwei.com/js-add-event.html">http://www.smartwei.com/js-add-event.html</a><br />
版权所有，转载时必须以超链接形式注明作者和原始出处及本声明。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.smartwei.com/js-add-event.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>javascript实现url跳转</title>
		<link>http://www.smartwei.com/javascript-url-redirect.html</link>
		<comments>http://www.smartwei.com/javascript-url-redirect.html#comments</comments>
		<pubDate>Mon, 01 Nov 2010 03:49:16 +0000</pubDate>
		<dc:creator>10V</dc:creator>
				<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://www.smartwei.com/?p=286</guid>
		<description><![CDATA[javascript实现url跳转，可以设置延时跳转]]></description>
			<content:encoded><![CDATA[<p>做下笔记, js实现url跳转,可以设置延时跳转:<br />
[js]<br />
function urlJump( url, secs)<br />
{<br />
	var secs = parseInt( secs ) &gt; 0 ? parseInt( secs ) * 1000 : 0;<br />
	if( !-[1,] )<br />
	{ //判断是否为IE浏览器。 当为IE浏览器时 [1,].toString()输出为&#8217;1,&#8217;, 其他浏览器输出为&#8217;1&#8242;;<br />
		var a = document.createElement( &#8216;a&#8217; );<br />
		a.href = url;<br />
		document.body.appendChild( a );<br />
		setTimeout(function(){a.click()}, secs);<br />
	}<br />
	else<br />
	{<br />
		setTimeout(&quot;location.href = &#8216;&quot; + url + &quot;&#8217;&quot;, secs);<br />
	}<br />
}<br />
[/js]</p>
<p>作者: <a href="http://www.smartwei.com">石巍</a><br />
原载: <a href="http://www.smartwei.com/javascript-url-redirect.html">10V的博客</a><br />
版权所有，转载时必须以超链接形式注明作者和原始出处及本声明。</p>
<p>本文链接: <a href="http://www.smartwei.com/javascript-url-redirect.html">http://www.smartwei.com/javascript-url-redirect.html</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.smartwei.com/javascript-url-redirect.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>非常实用的javascript设置、获取、删除cookie函数</title>
		<link>http://www.smartwei.com/javascript-cookie-functions.html</link>
		<comments>http://www.smartwei.com/javascript-cookie-functions.html#comments</comments>
		<pubDate>Mon, 01 Nov 2010 02:53:19 +0000</pubDate>
		<dc:creator>10V</dc:creator>
				<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://www.smartwei.com/?p=284</guid>
		<description><![CDATA[非常实用的javascript设置、获取、删除cookie函数]]></description>
			<content:encoded><![CDATA[<p>做下笔记，非常好用的javascript操作cookie函数：<br />
[js]<br />
//secure设置为ture时，只有是HTTPS连接时才设置cookie<br />
function setcookie( name, value, expires, path, domain, secure )<br />
{<br />
	var today = new Date();<br />
	today.setTime( today.getTime() );<br />
	var expire_date = new Date( today.getTime() + (expires * 1000 ) );<br />
	document.cookie = name + &#8216;=&#8217; + escape( value ) +<br />
		( ( expires ) ? &#8216;;expires=&#8217; + expire_date.toGMTString() : ” ) +<br />
		( ( path) ? &#8216;;path=&#8217; + path : ” ) +<br />
		( ( domain ) ? &#8216;;domain=&#8217; + domain : ” ) +<br />
		( ( secure ) ? &#8216;;secure&#8217; : ” );<br />
}</p>
<p>function getcookie( name )<br />
{<br />
	var start = document.cookie.indexOf( name + &quot;=&quot; );<br />
	var len = start + name.length + 1;<br />
	if( ( !start ) &amp;&amp; ( name != document.cookie.substring( 0, name.length ) ) )<br />
	{<br />
		return null;<br />
	}<br />
	if( start == -1 )<br />
	{<br />
		return null;<br />
	}<br />
	var end = document.cookie.indexOf( &#8216;;&#8217;, len );<br />
	if( end == -1 )<br />
	{<br />
		end = document.cookie.length;<br />
	}<br />
	return unescape( document.cookie.substring( len, end ) );<br />
}</p>
<p>function delcookie( name, path, domain )<br />
{<br />
	var exp = new Date();<br />
	exp.setTime( exp.getTime() &#8211; 1 );<br />
	var cval = getcookie( name );<br />
	document.cookie = name + &quot;=&quot; + cval + &quot;;expires=&quot; + exp.toGMTString() +<br />
		( ( path ) ? &#8216;;path&#8217; + path : ” ) +<br />
		( ( domain ) ? &#8216;;domain=&#8217; + domain : ” );<br />
} </p>
<p>[/js]</p>
<p>作者: <a href="http://www.smartwei.com">石巍</a><br />
原载: <a href="http://www.smartwei.com/javascript-cookie-functions.html">10V的博客</a><br />
版权所有，转载时必须以超链接形式注明作者和原始出处及本声明。</p>
<p>本文链接: <a href="http://www.smartwei.com/javascript-cookie-functions.html">http://www.smartwei.com/javascript-cookie-functions.html</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.smartwei.com/javascript-cookie-functions.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>深入理解 JavaScript闭包(closure)</title>
		<link>http://www.smartwei.com/javascript-closure.html</link>
		<comments>http://www.smartwei.com/javascript-closure.html#comments</comments>
		<pubDate>Fri, 02 Jul 2010 03:26:55 +0000</pubDate>
		<dc:creator>10V</dc:creator>
				<category><![CDATA[javascript]]></category>
		<category><![CDATA[javascript 闭包]]></category>

		<guid isPermaLink="false">http://www.smartwei.com/?p=272</guid>
		<description><![CDATA[深入理解 JavaScript闭包(closure) - 本文介绍了闭包的基本概念、微观世界、以及应用场景，对于学习javascript闭包的朋友很有帮助]]></description>
			<content:encoded><![CDATA[<p>最近在网上查阅了不少Javascript闭包(closure)相关的资料，写的大多是非常的学术和专业。对于初学者来说别说理解闭包了，就连文字叙述都很难看懂。撰写此文的目的就是用最通俗的文字揭开Javascript闭包的真实面目。</p>
<p><strong>一、什么是闭包？</strong><br />
“官方”的解释是：闭包是一个拥有许多变量和绑定了这些变量的环境的表达式（通常是一个函数），因而这些变量也是该表达式的一部分。<br />
相信很少有人能直接看懂这句话，因为他描述的太学术。其实这句话通俗的来说就是：JavaScript中所有的function都是一个闭包。不过一般来说，嵌套的function所产生的闭包更为强大，也是大部分时候我们所谓的“闭包”。看下面这段代码：<br />
[js]<br />
function a() {<br />
    var i = 0;<br />
    function b() {<br />
        alert(++i);<br />
    }<br />
    return b;<br />
}<br />
var c = a();<br />
c();<br />
[/js]</p>
<p><span id="more-272"></span><br />
这段代码有两个特点：</p>
<ol>
<li>函数b嵌套在函数a内部；</li>
<li>函数a返回函数b。</li>
</ol>
<p>引用关系如图：<br />
<a href="http://www.smartwei.com/javascript-closure.html"><img src="http://www.smartwei.com/wp-content/uploads/2010/07/jsclosure.jpg" alt="jsclosure" title="jsclosure" width="228" height="175" class="aligncenter size-full wp-image-273" /></a></p>
<blockquote style="color:#C00; font-weight:bold"><p>
当函数a的内部函数b被函数a外的一个变量引用的时候，就创建了一个我们通常所谓的“闭包”。
</p></blockquote>
<p>让我们说的更透彻一些。所谓“闭包”，就是在构造函数体内定义另外的函数作为目标对象的方法函数，而这个对象的方法函数反过来引用外层函数体中的临时变量。这使得只要目标 对象在生存期内始终能保持其方法，就能间接保持原构造函数体当时用到的临时变量值。尽管最开始的构造函数调用已经结束，临时变量的名称也都消失了，但在目 标对象的方法内却始终能引用到该变量的值，而且该值只能通这种方法来访问。即使再次调用相同的构造函数，但只会生成新对象和方法，新的临时变量只是对应新 的值，和上次那次调用的是各自独立的。</p>
<p>为了更深刻的理解闭包，下面让我们继续探索闭包的作用和效果。</p>
<p><strong>二、闭包有什么作用和效果？</strong><br />
简而言之，闭包的作用就是在a执行完并返回后，闭包使得Javascript的垃圾回收机制GC不会收回a所占用的资源，因为a的内部函数b的执行需要依赖a中的变量。这是对闭包作用的非常直白的描述，不专业也不严谨，但你一定能看懂。理解闭包需要循序渐进的过程。<br />
在上面的例子中，由于闭包的存在使得函数a返回后，a中的i始终存在，这样每次执行c()，i都是自加1后alert出i的值。</p>
<p>那么我们来想象另一种情况，如果a返回的不是函数b，情况就完全不同了。因为a执行完后，b没有被返回给a的外界，只是被a所引用，而此时a也只会被b引用，因此函数a和b互相引用但又不被外界打扰(被外界引用)，函数a和b就会被GC回收。(关于Javascript的垃圾回收机制将在后面详细介绍)</p>
<p><strong>三、闭包的微观世界</strong><br />
如果要更加深入的了解闭包以及函数a和嵌套函数b的关系，我们需要引入另外几个概念：函数的执行环境(excution context)、活动对象(call object)、作用域(scope)、作用域链(scope chain)。以函数a从定义到执行的过程为例阐述这几个概念。</p>
<ol>
<li>当定义函数a的时候，js解释器会将函数a的作用域链(scope chain)设置为定义a时a所在的“环境”，如果a是一个全局函数，则scope chain中只有window对象。</li>
<li>当执行函数a的时候，a会进入相应的执行环境(excution context)。</li>
<li>在创建执行环境的过程中，首先会为a添加一个scope属性，即a的作用域，其值就为第1步中的scope chain。即a.scope=a的作用域链。</li>
<li>然后执行环境会创建一个活动对象(call object)。活动对象也是一个拥有属性的对象，但它不具有原型而且不能通过JavaScript代码直接访问。创建完活动对象后，把活动对象添加到a的作用域链的最顶端。此时a的作用域链包含了两个对象：a的活动对象和window对象。</li>
<li>下一步是在活动对象上添加一个arguments属性，它保存着调用函数a时所传递的参数。</li>
<li>最后把所有函数a的形参和内部的函数b的引用也添加到a的活动对象上。在这一步中，完成了函数b的的定义，因此如同第3步，函数b的作用域链被设置为b所被定义的环境，即a的作用域。</li>
</ol>
<p>到此，整个函数a从定义到执行的步骤就完成了。此时a返回函数b的引用给c，又函数b的作用域链包含了对函数a的活动对象的引用，也就是说b可以访问到a中定义的所有变量和函数。函数b被c引用，函数b又依赖函数a，因此函数a在返回后不会被GC回收。</p>
<p>当函数b执行的时候亦会像以上步骤一样。因此，执行时b的作用域链包含了3个对象：b的活动对象、a的活动对象和window对象，如下图所示：<br />
<a href="http://www.smartwei.com/javascript-closure.html"><img src="http://www.smartwei.com/wp-content/uploads/2010/07/jsclosure-scopechain.jpg" alt="jsclosure-scopechain" title="jsclosure-scopechain" width="500" height="180" class="aligncenter size-full wp-image-274" /></a><br />
如图所示，当在函数b中访问一个变量的时候，搜索顺序是：</p>
<ol>
<li>先搜索自身的活动对象，如果存在则返回，如果不存在将继续搜索函数a的活动对象，依次查找，直到找到为止。</li>
<li>如果函数b存在prototype原型对象，则在查找完自身的活动对象后先查找自身的原型对象，再继续查找。这就是Javascript中的变量查找机制。</li>
<li>如果整个作用域链上都无法找到，则返回undefined。</li>
</ol>
<p>小结，本段中提到了两个重要的词语：函数的定义与执行。文中提到函数的作用域是在定义函数时候就已经确定，而不是在执行的时候确定（参看步骤1和3）。用一段代码来说明这个问题：<br />
[js]<br />
function f(x) {<br />
    var g = function () { return x; }<br />
    return g;<br />
}<br />
var h = f(1);<br />
alert(h());<br />
[/js]<br />
这段代码中变量h指向了f中的那个匿名函数(由g返回)。</p>
<ul>
<li>假设函数h的作用域是在执行alert(h())确定的，那么此时h的作用域链是：h的活动对象->alert的活动对象 ->window对象。</li>
<li>假设函数h的作用域是在定义时确定的，就是说h指向的那个匿名函数在定义的时候就已经确定了作用域。那么在执行的时候，h的作用域链为：h的活动对象->f的活动对象->window对象。</li>
</ul>
<p>如果第一种假设成立，那输出值就是undefined；如果第二种假设成立，输出值则为1。</p>
<p>运行结果证明了第2个假设是正确的，说明函数的作用域确实是在定义这个函数的时候就已经确定了。</p>
<p><strong>四、闭包的应用场景</strong></p>
<ol>
<li>保护函数内的变量安全。以最开始的例子为例，函数a中i只有函数b才能访问，而无法通过其他途径访问到，因此保护了i的安全性。</li>
<li>在内存中维持一个变量。依然如前例，由于闭包，函数a中i的一直存在于内存中，因此每次执行c()，都会给i自加1。</li>
<li>通过保护变量的安全实现JS私有属性和私有方法（不能被外部访问）推荐阅读：http://javascript.crockford.com/private.html<br />
私有属性和方法在Constructor外是无法被访问的 </li>
</ol>
<p>[js]<br />
function Constructor(&#8230;) {<br />
    var that = this;<br />
    var membername = value;<br />
    function membername(&#8230;) {&#8230;}<br />
}<br />
[/js]<br />
以上3点是闭包最基本的应用场景，很多经典案例都源于此。</p>
<p><strong>五、Javascript的垃圾回收机制</strong><br />
在Javascript中，如果一个对象不再被引用，那么这个对象就会被GC回收。如果两个对象互相引用，而不再被第3者所引用，那么这两个互相引用的对象也会被回收。因为函数a被b引用，b又被a外的c引用，这就是为什么函数a执行后不会被回收的原因。</p>
<p><strong>六、结语</strong><br />
理解JavaScript的闭包是迈向高级JS程序员的必经之路，理解了其解释和运行机制才能写出更为安全和优雅的代码。如果您对本文有任何的建议和疑问，欢迎留言。</p>
<p>作者: <a href="http://www.smartwei.com">石巍</a><br />
原载: <a href="http://www.felixwoo.com/archives/247">Felix Woo &#8211; 深入理解 JavaScript闭包(closure)</a><br />
版权所有，转载时必须以超链接形式注明作者和原始出处及本声明。</p>
<p>本文链接: <a href="http://www.smartwei.com/javascript-closure.html">http://www.smartwei.com/javascript-closure.html</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.smartwei.com/javascript-closure.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>javascript常用正则表达式</title>
		<link>http://www.smartwei.com/javascript-reg.html</link>
		<comments>http://www.smartwei.com/javascript-reg.html#comments</comments>
		<pubDate>Thu, 01 Jul 2010 05:51:35 +0000</pubDate>
		<dc:creator>10V</dc:creator>
				<category><![CDATA[javascript]]></category>
		<category><![CDATA[正则表达式]]></category>

		<guid isPermaLink="false">http://www.smartwei.com/?p=268</guid>
		<description><![CDATA[这篇文章列出了一些常用的javascript正则表达式，希望对大家有用]]></description>
			<content:encoded><![CDATA[<p>正则表达式用于字符串处理，表单验证等场合，实用高效，但用到时总是不太把握，以致往往要上网查一番。这里整理出了一些常用的表达式收藏在这里，作备忘之用。</p>
<p><strong>匹配中文字符的正则表达式：</strong> [\u4e00-\u9fa5]</p>
<p><strong>匹配双字节字符(包括汉字在内)：</strong>[^\x00-\xff]</p>
<p><strong>应用：计算字符串的长度</strong>（一个双字节字符长度计2，ASCII字符计1）</p>
<p>String.prototype.len=function(){return this.replace([^\x00-\xff]/g,”aa”).length;}</p>
<p><strong>匹配空行的正则表达式：</strong>\n[\s| ]*\r</p>
<p><strong>匹配HTML标记的正则表达式：</strong>/&lt;(.*)&gt;.*&lt;\/\1&gt;|&lt;(.*) \/&gt;/</p>
<p><strong>匹配首尾空格的正则表达式：</strong>(^\s*)|(\s*$)</p>
<p>应用：javascript中没有像vbscript那样的<strong>trim函数</strong>，我们就可以利用这个表达式来实现，如下：</p>
<p>String.prototype.trim = function()<br />
{<br />
return this.replace(/(^\s*)|(\s*$)/g, “”);<br />
}</p>
<p><strong>匹配Email地址的正则表达式</strong>：\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*</p>
<p><strong>匹配网址URL的正则表达式：</strong>http://([\w-]+\.)+[\w-]+(/[\w- ./?%&amp;=]*)?</p>
<p><strong>利用正则表达式去除字串中重复的字符的算法程序：</strong><br />
var s=”abacabefgeeii”<br />
var s1=s.replace(/(.).*\1/g,”$1&#8243;)<br />
var re=new RegExp(“["+s1+"]“,”g”)<br />
var s2=s.replace(re,”")<br />
alert(s1+s2) //结果为：abcefgi<br />
思路是使用后向引用取出包括重复的字符，再以重复的字符建立第二个表达式，取到不重复的字符，两者串连。这个方法对于字符顺序有要求的字符串可能不适用。</p>
<p><strong>得用正则表达式从URL地址中提取文件名的javascript程序</strong>，如下结果为page1<br />
s=”http://www.gzcynet/page1.htm”<br />
s=s.replace(/(.*\/){0,}([^\.]+).*/ig,”$2&#8243;)<br />
alert(s)</p>
<p><strong>用正则表达式限制只能输入中文：</strong>onkeyup=”value=value.replace(/[^\u4E00-\u9FA5]/g,”)” onbeforepaste=”clipboardData.setData(&#8216;text&#8217;,clipboardData.getData(&#8216;text&#8217;).replace(/[^\u4E00-\u9FA5]/g,”))”</p>
<p><strong>用正则表达式限制只能输入全角字符：</strong> onkeyup=”value=value.replace(/[^\uFF00-\uFFFF]/g,”)” onbeforepaste=”clipboardData.setData(&#8216;text&#8217;,clipboardData.getData(&#8216;text&#8217;).replace(/[^\uFF00-\uFFFF]/g,”))”<br />
<strong><br />
用正则表达式限制只能输入数字：</strong>onkeyup=”value=value.replace(/[^\d]/g,”) “onbeforepaste=”clipboardData.setData(&#8216;text&#8217;,clipboardData.getData(&#8216;text&#8217;).replace(/[^\d]/g,”))”</p>
<p><strong>用正则表达式限制只能输入数字和英文：</strong>onkeyup=”value=value.replace(/[\W]/g,”) “onbeforepaste=”clipboardData.setData(&#8216;text&#8217;,clipboardData.getData(&#8216;text&#8217;).replace(/[^\d]/g,”))”</p>
<p>作者: <a href="http://www.smartwei.com">石巍</a><br />
版权所有，转载时必须以超链接形式注明作者和原始出处及本声明。</p>
<p>本文链接: <a href="http://www.smartwei.com/javascript-reg.html">http://www.smartwei.com/javascript-reg.html</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.smartwei.com/javascript-reg.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>XPath 知识入门  &#8211; jQuery使用XPath</title>
		<link>http://www.smartwei.com/xpath-vs-jquery.html</link>
		<comments>http://www.smartwei.com/xpath-vs-jquery.html#comments</comments>
		<pubDate>Tue, 11 May 2010 07:48:39 +0000</pubDate>
		<dc:creator>10V</dc:creator>
				<category><![CDATA[javascript]]></category>
		<category><![CDATA[jquery]]></category>
		<category><![CDATA[xpath]]></category>

		<guid isPermaLink="false">http://www.smartwei.com/?p=224</guid>
		<description><![CDATA[学习使用 XPath 1.0 和 jQuery 1.4 处理类似的任务，让您能够在必要的时候从其中一个快速转向另一个。]]></description>
			<content:encoded><![CDATA[<p>jQuery可以通过类似于CSS或者xPath的语法来获取页面中的元素。在本文中，一起来比较和学习使用 XPath 1.0 和 jQuery 1.4 处理类似的任务，让您能够在必要的时候从其中一个快速转向另一个。</p>
<h3>例子</h3>
<p>整篇文章中，都会回过头来参考一个方便的样例 XML 文档，参见 清单 1。此书籍列表包括各种信息，比如作者、两种完全虚构的价格和书名。<br />
<b>清单1:</b> 样例 XML 文档 (book.xml)<br />
[html]</p>
<p>&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;<br />
&lt;catalog&gt;<br />
    &lt;book format=&quot;trade&quot;&gt;<br />
        &lt;name&gt;Jennifer Government&lt;/name&gt;<br />
        &lt;author&gt;Max Barry&lt;/author&gt;<br />
        &lt;price curr=&quot;CAD&quot;&gt;15.00&lt;/price&gt;<br />
        &lt;price curr=&quot;USD&quot;&gt;12.00&lt;/price&gt;<br />
    &lt;/book&gt;</p>
<p>    &lt;book format=&quot;textbook&quot;&gt;<br />
        &lt;name&gt;Unity Game Development Essentials&lt;/name&gt;<br />
        &lt;author&gt;Will Goldstone&lt;/author&gt;<br />
        &lt;price curr=&quot;CAD&quot;&gt;52.00&lt;/price&gt;<br />
        &lt;price curr=&quot;USD&quot;&gt;45.00&lt;/price&gt;<br />
    &lt;/book&gt;</p>
<p>    &lt;book format=&quot;textbook&quot;&gt;<br />
        &lt;name&gt;UNIX Visual QuickPro&lt;/name&gt;<br />
        &lt;author&gt;Chris Herborth&lt;/author&gt;<br />
        &lt;price curr=&quot;CAD&quot;&gt;15.00&lt;/price&gt;<br />
        &lt;price curr=&quot;USD&quot;&gt;10.00&lt;/price&gt;<br />
    &lt;/book&gt;<br />
&lt;/catalog&gt;</p>
<p>[/html]<br />
<span id="more-224"></span></p>
<h3>XPath 假定</h3>
<p>对于本文中的 XPath 代码，您要做以下假定：</p>
<ul>
<li>已经将 book.xml 文件（参见 清单 1）加载到您的 XPath 实现可以使用的格式。</li>
<li>从一个表示文档根的对象开始搜索。就是以 <catalog> 元素作为子元素的那个对象。您将称之为 root，因为它是 XML 文档层次结构的根。</li>
</ul>
<p>由于在太多不同的平台上有太多的 XPath 实现，所以下面我们将重点放在 XPath 语句本身上，并使用一个类似于 JavaScript 的伪代码来在上下文中展示这些语句；请查看您喜欢的开发平台的类库，了解有关加载 XML 文档和您可用的特定 XML 节点对象的信息。</p>
<h3>jQuery 假定</h3>
<p>本文中的 jQuery 代码做以下假定：</p>
<ul>
<li>使用的是最新（版本 1.4.0）jQuery 代码（参见 参考资料 中的链接）。</li>
<li>已经通过 jQuery.get() 或 jQuery.post() 方法加载了 book.xml 文件，并且已经将最终的 XML 文档存储在一个名为 root 的变量中（与 XPath 例子相同）。</li>
</ul>
<p>用于做这件事的一些样例代码在 清单 2 中。<br />
<b>清单2:</b>利用 jQuery 加载 XML 样例<br />
[html]<br />
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;<br />
&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Strict//EN&quot;<br />
               &quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd&quot;&gt;<br />
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot;&gt;<br />
&lt;head&gt;<br />
&lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html;charset=utf-8&quot;/&gt;<br />
&lt;title&gt;Book Catalog&lt;/title&gt;<br />
&lt;script type=&quot;text/javascript&quot;<br />
src=&quot;http://ajax.googleapis.com/ajax/libs/jquery/1.4.0/jquery.min.js&quot;&gt;&lt;/script&gt;<br />
&lt;script type=&quot;text/javascript&quot;&gt;// &lt;![CDATA[<br />
var root = null;</p>
<p>$(document).ready( function(){<br />
    $.get( &quot;http://localhost/~chrish/books.xml&quot;,<br />
        function( data ) {<br />
            root = data;</p>
<p>            $(&quot;p#status&quot;).text( &quot;Loaded.&quot; );<br />
        } );<br />
} );<br />
// ]]&gt;&lt;/script&gt;<br />
&lt;/head&gt;</p>
<p>&lt;body&gt;<br />
&lt;p id=&quot;status&quot;&gt;<br />
Loading book.xml&#8230;<br />
&lt;/p&gt;<br />
&lt;/body&gt;<br />
&lt;/html&gt;</p>
<p>[/html]<br />
在 $(document).ready() 函数中，使用 jQuery get() 方法从本地 Web 服务器加载 books.xml，将最终的文档对象存储在 root 变量中，并用 status  ID 设置段落的文本，以表明 XML 已完成加载。有关 jQuery 的更多信息，请查看本文末尾 参考资料 中的相关链接列表。</p>
<h3>选择节点</h3>
<p>XPath 和 jQuery 的基本目的都是从文档选择节点。一旦选择了一个节点（或一个节点集合），就可以找到您正在寻找的数据以及在需要时操纵文档。<br />
XPath 设计用于确切返回您所寻找的节点；它一般非常特定。另一方面，jQuery 则使得操作大型节点集合非常容易，所以有时候您必须在开始处理节点之前小心地缩小匹配范围。</p>
<h3>按名称选择节点</h3>
<p>在搜索特定节点时，您通常知道它的名称，或者知道其父元素的名称。<br />
要找到一个特定的元素，您会使用它的名称，如 清单 3 所示。<br />
<b>清单3:</b>按名称选择节点<br />
[html]</p>
<p>/* Find all &lt;book&gt; elements through XPath: */<br />
var result = root.find( &quot;//book&quot; );</p>
<p>/* Find all &lt;book&gt; elements through jQuery: */<br />
var result = $(root).find( &quot;book&quot; );</p>
<p>[/html]<br />
用于选择所有 <book> 元素的 XPath 语句（//book）使用两个斜杠 (//)，来指定从当前节点（本例中是 root）开始、所有匹配的节点都会被找到。这是 jQuery 的默认行为，所以您不需要包含任何其他内容。在两种情况下，结果都是 清单 1 中的所有三个 <book> 元素。</p>
<p>通常可以通过指定元素路径来缩小搜索结果；结果将是自路径末尾的匹配节点（参见 清单 4）。<br />
<b>清单4:</b>按路径选择节点—两者行为不同<br />
[html]</p>
<p>/* Be more specific (XPath): */<br />
var result = root.find( &quot;/catalog//book&quot; );</p>
<p>/* Be more specific (jQuery): */<br />
var result = $(root).find( &quot;catalog book&quot; );</p>
<p>[/html]<br />
从根元素 (/) 开始，这个 XPath 语句将寻找第一个 <catalog> 元素，然后返回这第一个 <catalog> 元素下的所有 <book> 元素。jQuery 语句的行为稍有不同；它将返回所有 <catalog> 元素下的所有 <book> 元素（参见 清单 5）。对于例子 book.xml 文件，结果是相同的节点集，但是如果您想要得到 <book> 元素下的所有 <author> 元素，那会怎么样呢？跟 清单 3 中一样，应该以两个斜杠 (//) 开始 XPath 表达式。<br />
<b>清单5:</b>按路径找出内含的节点—两个例子的行为一样<br />
[html]</p>
<p>/* Get all authors from all books (XPath): */<br />
var result = root.find( &quot;//book//author&quot; );</p>
<p>/* Get all authors from all books (jQuery): */<br />
var result = $(root).find( &quot;book author&quot; );</p>
<p>[/html]<br />
要让 jQuery 跟 清单 4 中的 XPath 样例一样返回第一个 <catalog> 中的 <book> 元素，您必须指导它使用它找到的第一个 <catalog>（参见 清单 6）。<br />
<b>清单6:</b> 匹配第一个 catalog 中的 book—这些例子的行为一样<br />
[html]</p>
<p>/* All books from the first catalog (XPath): */<br />
var result = root.find( &quot;/catalog//book&quot; );</p>
<p>/* All books from the first catalog (jQuery): */<br />
var result = $(root).find( &quot;catalog:first book&quot; );</p>
<p>[/html]<br />
找到元素的最后一次出现（比如项目列表中的最后一个列表项，或者选择列表中的最后一个选项）也是一个常见操作。要正确地将一些东西附加到列表末尾，需要知道此末尾的位置（参见 清单 7）。<br />
<b>清单7:</b> 找到 catalog 中的最后一个 book<br />
[html]</p>
<p>/* The last book from the first catalog (XPath): */<br />
var result = root.find( &quot;/catalog/book[last()]&quot; );</p>
<p>/* The last book from the first catalog (jQuery): */<br />
var result = $(root).find( &quot;catalog:first book:last&quot; );</p>
<p>[/html]<br />
在两种情况下，您都得到第一个 <catalog> 元素中的最后一个 <book> 元素，这正是您在寻找的。在 XPath 例子中，last() 函数返回最后匹配元素的索引（用在方括号中）。</p>
<h3>选择任意节点</h3>
<p>有时，您不知道您在寻找的元素的名称，或者需要找到一个可能在几个不同元素中的元素。在 XPath 和 jQuery 中，都可以使用星号 (*) 来匹配任意元素（参见 清单 8）。<br />
<b>清单8:</b> any 元素<br />
[html]</p>
<p>/* Find all authors in all elements inside of &lt;catalog&gt; (XPath): */<br />
var result = root.find( &quot;/catalog//*//author&quot; );</p>
<p>/* Find all authors in all elements inside of &lt;catalog&gt; (jQuery): */<br />
var result = $(root).find( &quot;catalog:first * author&quot; );</p>
<p>[/html]<br />
注意，我在 jQuery 样例中使用了 :first，以使它的行为完全跟 XPath 版本一样。</p>
<h3>按属性选择节点</h3>
<p>类似的元素通常具有独特的属性，比如 XHTML 元素中使用的 id 属性，是为了给 XHTML 元素一个惟一的引用 ID（参见 清单 9）。有时，您并不太关心特定的元素，而是关心一个属性为特定值的元素。<br />
<b>清单9:</b>找到那些讨厌的教科书<br />
[html]</p>
<p>/* Find all books that are textbooks (XPath): */<br />
var result = root.find( &quot;//book[@format='textbook']&quot; );</p>
<p>/* Find all books that are textbooks (jQuery): */<br />
var result = $(root).find( &quot;book[format='textbook']&quot; );</p>
<p>[/html]<br />
两个例子都将返回所有具有 format 属性且属性值设置为 textbook 的 <book> 元素（清单 1 中的 book.xml 文件中有两个这样的元素）。XPath 的语法使用一个 @ 符号来匹配属性（jQuery 只是将属性括在方括号中），您需要包含两个斜杠 (//) 来匹配所有 <book> 元素，但是两个查询非常类似，都很直观。</p>
<p>针对 XHTML 中两个最常见的匹配属性（id 和 class），jQuery 包含了两个快捷方式。在 XPath 中，您必须显式地写出它们（参见 清单 10）。<br />
<b>清单9:</b>找到那些讨厌的教科书<br />
[html]<br />
/* Find the &quot;status&quot; &lt;p&gt;, then the highlighted elements (XPath) */<br />
var result1 = xhtml_root.find( &quot;//p[@id='status']&quot; );<br />
var result2 = xhtml_root.find( &quot;//*[@class='highlight']&quot; );</p>
<p>/* Find the &quot;status&quot; &lt;p&gt;, then the highlighted elements (jQuery) */<br />
var result1 = $( &quot;p#status&quot; );<br />
var result2 = $( &quot;.highlight&quot; );</p>
<p>[/html]<br />
假设您的 XHTML 文档是有效的（确实是的，对吧？），ID 匹配查询将只返回一个元素，因为在有效的 XML 文档中，ID 必须是惟一的。</p>
<p>如果您是层叠样式表（Cascading Style Sheets，CSS）的粉丝，可能注意到了，jQuery 选择器几乎跟 CSS 选择器完全相同。这很方便，因为您只需要记住一个针对通过 jQuery 找到想要的元素和利用 CSS 为元素定义样式的标准。</p>
<h3>模拟高级 XPath 特性</h3>
<p>XPath 指定了很多在 jQuery 中不必要的有用特性；毕竟，jQuery 运行在浏览器中，可以充分利用 JavaScript 的优势，而 XPath 通常用于比较受限的环境中，比如 XSLT 处理。</p>
<p>当然，只要您想用，这并不能阻止您用 JavaScript 实现这些特性。</p>
<p>很容易数清查询结果的个数（参见 清单 10）。<br />
<b>清单10:</b>多少节点匹配选择器？<br />
[html]</p>
<p>/* How many price entries do you have? (XPath) */<br />
var result = root.find( &quot;count(//price)&quot; );</p>
<p>/* How many price entries do you have? (jQuery) */<br />
var result = $(root).find( &quot;price&quot; ).length;</p>
<p>[/html]<br />
有时只需要知道节点是否包含某个字符串（参见 清单 11）。<br />
<b>清单11:</b>第三个 <author> 中包含 Chris 吗？<br />
[html]</p>
<p>/* Does the third &lt;author&gt; have &quot;Chris&quot; in its contents? (XPath) */<br />
var result = root.find( &quot;contains(//book[3]/author,&#8217;Chris&#8217;)&quot; );</p>
<p>/* Does the third &lt;author&gt; have &quot;Chris&quot; in its contents? (jQuery) */<br />
var result = $(root).find( &quot;book:eq(2) author:contains(&#8216;Chris&#8217;)&quot; ).length &gt; 0</p>
<p>[/html]<br />
清单 11 中有一个非常重要的区别需要注意，XPath 的索引从 1 开始，不是从 0 开始。在 jQuery 中，必须使用 :eq(2)  来得到第三个结果。</p>
<p>XPath 也有一个 sum() 函数，它以匹配节点的内容作为参数，将这些参数转换成数值，并返回这些值的和。在使用 jQuery 时，必须编写一个简短的函数来模拟该函数（参见 清单 12）。<br />
<b>清单11:</b>计算一些节点内容的和<br />
[html]<br />
/* Sum the Canadian prices (XPath) */<br />
var result = root.find( &quot;sum(//price[@curr='CAD'])&quot; );</p>
<p>/* Sum the Canadian prices (jQuery) */<br />
function sum( root, selector ) {<br />
    var x = 0;<br />
    $(root).find( selector ).map( function() {<br />
        if( this.text ) {<br />
            // Internet Explorer-only<br />
            return x += ( this.text * 1 );<br />
        }</p>
<p>        // Firefox and W3C-compliant browsers<br />
        return x += ( this.textContent * 1 );<br />
    } );<br />
    return x;<br />
}</p>
<p>var result = sum( root, &quot;price[curr='CAD']&quot; );</p>
<p>[/html]<br />
jQuery 中的 map() 方法为每个结果节点运行指定的函数。注意，要得到结果节点的内容，也必须稍微费点事。确保在所有您喜欢的浏览器上测试这类 JavaScript。</p>
<p>您现在应该比较能理解何时以及如何将 XPath 1.0 和 jQuery 1.4 用于类似的任务了。</p>
<p>作者: <a href="www.smartwei.com">石巍</a><br />
原载: <a href="http://www.ibm.com/developerworks/cn/xml/x-xpathjquery/?ca=drs-tp4608">IBM – 利用 XPath-jQuery 集锦手册在 XPath 和 jQuery 之间做选择</a><br />
版权所有，转载时必须以超链接形式注明作者和原始出处及本声明。</p>
<p>本文链接: <a href="http://www.smartwei.com/xpath-vs-jquery.html">http://www.smartwei.com/xpath-vs-jquery.html</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.smartwei.com/xpath-vs-jquery.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

