<?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>潔靜精微 &#187; js</title>
	<atom:link href="http://julabs.me/blog/tags/js/feed/" rel="self" type="application/rss+xml" />
	<link>http://julabs.me/blog</link>
	<description>想努力创造完美的东西，必须具备心灵的纯洁，同时富于宗教精神。</description>
	<lastBuildDate>Wed, 18 Jan 2012 06:34:33 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.4</generator>
		<item>
		<title>window.location的用法</title>
		<link>http://julabs.me/blog/front/javascript-window-location/</link>
		<comments>http://julabs.me/blog/front/javascript-window-location/#comments</comments>
		<pubDate>Thu, 24 Mar 2011 16:44:55 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[前端]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[js]]></category>
		<category><![CDATA[location]]></category>

		<guid isPermaLink="false">http://julabs.me/blog/?p=364</guid>
		<description><![CDATA[参考地址：window.location 工作中经常要对window.location进行相关的操作，在这里列出它的属性和方法，方便查找。现以链接http://julabs.me:8080/blog/front/javascript-window-location.html?author=julabs#comment为例来讲解window.location的属性： 属性 详解 例样 hash URL中在“#”号后面的部分，包括“#”在内 #comment host 主机名和端口号 julabs.me:8080 hostname 主机名，不包括端口号 julabs.me href 整个URL地址 http://julabs.me:8080/blog/front/javascript-window-location.html?author=julabs#comment pathname 相对于主机名和端口号的路径 /blog/front/javascript-window-location.html port 地址的端口号 8080 protocol 地址的协议 http:// search URL中在“?”号后面的部分，包括“?”在内 ?author=julabs 下表列出的是window.location的方法： 方法 详解 assign(url) 根据参数url所提供的地址来载入相应的页面 reload(forceget) 重载当前的页面，参数forceget是个boolean类型的值。当forceget为true时，页面会请求从服务器载入，如果为false则直接从缓存载入，默认为false replace(url) 将当前页面替换成参数url所对应的页面。与assign()方法的差别就在于，replace()方法不会将前一个页面地址保存在历史记录中，所以也就不能通过返回按钮回到前一个地址页面 toString() 返回Location所对应的URL值，相当于window.location.href]]></description>
			<content:encoded><![CDATA[<p>参考地址：<a href="https://developer.mozilla.org/en/DOM/window.location" target="_blank">window.location</a></p>
<p>工作中经常要对<strong>window.location</strong>进行相关的操作，在这里列出它的属性和方法，方便查找。现以链接<strong>http://julabs.me:8080/blog/front/javascript-window-location.html?author=julabs#comment</strong>为例来讲解<strong>window.location</strong>的属性：</p>
<table>
<thead>
<tr>
<th>属性</th>
<th>详解</th>
<th>例样</th>
</tr>
</thead>
<tbody>
<tr>
<td>hash</td>
<td>URL中在“#”号后面的部分，包括“#”在内</td>
<td>#comment</td>
</tr>
<tr>
<td>host</td>
<td>主机名和端口号</td>
<td>julabs.me:8080</td>
</tr>
<tr>
<td>hostname</td>
<td>主机名，不包括端口号</td>
<td>julabs.me</td>
</tr>
<tr>
<td>href</td>
<td>整个URL地址</td>
<td>http://julabs.me:8080/blog/front/javascript-window-location.html?author=julabs#comment</td>
</tr>
<tr>
<td>pathname</td>
<td>相对于主机名和端口号的路径</td>
<td>/blog/front/javascript-window-location.html</td>
</tr>
<tr>
<td>port</td>
<td>地址的端口号</td>
<td>8080</td>
</tr>
<tr>
<td>protocol</td>
<td>地址的协议</td>
<td>http://</td>
</tr>
<tr>
<td>search</td>
<td>URL中在“?”号后面的部分，包括“?”在内</td>
<td>?author=julabs</td>
</tr>
</tbody>
</table>
<p>下表列出的是<strong>window.location</strong>的方法：</p>
<table>
<thead>
<tr>
<th>方法</th>
<th>详解</th>
</tr>
</thead>
<tbody>
<tr>
<td>assign(url)</td>
<td>根据参数<strong>url</strong>所提供的地址来载入相应的页面</td>
</tr>
<tr>
<td>reload(forceget)</td>
<td>重载当前的页面，参数<strong>forceget</strong>是个<strong>boolean</strong>类型的值。当<strong>forceget</strong>为<strong>true</strong>时，页面会请求从服务器载入，如果为<strong>false</strong>则直接从缓存载入，默认为<strong>false</strong></td>
</tr>
<tr>
<td>replace(url)</td>
<td>将当前页面替换成参数<strong>url</strong>所对应的页面。与<strong>assign()</strong>方法的差别就在于，<strong>replace()</strong>方法不会将前一个页面地址保存在历史记录中，所以也就不能通过返回按钮回到前一个地址页面</td>
</tr>
<tr>
<td>toString()</td>
<td>返回<strong>Location</strong>所对应的URL值，相当于<code>window.location.href</code></td>
</tr>
</tbody>
</table>
]]></content:encoded>
			<wfw:commentRss>http://julabs.me/blog/front/javascript-window-location/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>正则表达式验证身份证</title>
		<link>http://julabs.me/blog/front/regular-id-card-number/</link>
		<comments>http://julabs.me/blog/front/regular-id-card-number/#comments</comments>
		<pubDate>Tue, 22 Feb 2011 12:39:23 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[前端]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[js]]></category>
		<category><![CDATA[regular]]></category>
		<category><![CDATA[正则]]></category>
		<category><![CDATA[身份证]]></category>

		<guid isPermaLink="false">http://julabs.me/blog/?p=361</guid>
		<description><![CDATA[下面是一个简单的正则表达式验证身份证函数： function isIdCardNo(arg){ return /(^\d{15}$)&#124;(^\d{17}(?:\d&#124;x&#124;X)$)/.test(arg); } 当然这个函数非常简单，不过能用就可以了。]]></description>
			<content:encoded><![CDATA[<p>下面是一个简单的正则表达式验证身份证函数：</p>
<pre><code class="javascript">function isIdCardNo(arg){
	return /(^\d{15}$)|(^\d{17}(?:\d|x|X)$)/.test(arg);
}
</code></pre>
<p>当然这个函数非常简单，不过能用就可以了。</p>
]]></content:encoded>
			<wfw:commentRss>http://julabs.me/blog/front/regular-id-card-number/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>JavaScript压缩工具</title>
		<link>http://julabs.me/blog/soft/tools-for-javascript-compressor/</link>
		<comments>http://julabs.me/blog/soft/tools-for-javascript-compressor/#comments</comments>
		<pubDate>Sun, 12 Sep 2010 15:53:38 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[软件]]></category>
		<category><![CDATA[compressor]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[js]]></category>
		<category><![CDATA[tool]]></category>

		<guid isPermaLink="false">http://julabs.me/blog/?p=263</guid>
		<description><![CDATA[JavaScript压缩工具很多，常用的可能就是YUICompressor、Closure Compiler、Packer，但我最常用的还是YUICompressor。 YUICompressor YUICompressor是建立在rhino interpreter基础上的，所以它的特点就是安全。YUICompressor是用Java编写的，要运行它首先要配置好Java环境。YUICompressor的压缩内容如下： 移除注释 移除额外的空格 细微优化 标识符替换（Identifier Replacement） 使用YUICompressor的命令行代码如下： java -jar yuicompressor-x.y.z.jar myfile.js -o myfile-min.js --charset utf-8 YUICompressor在压缩时还能够自动检查JS代码是否有错误，如果有错误它会列出错误的行数和原因。更难得的是，它也可以压缩CSS文件，对于前端人员简直就是一把多功能的瑞士军刀。 淘宝UED部把YUICompressor封装成了TBCompressor，这里有篇《TBCompressor介绍》，使用TBCompressor更加简单快捷。 Closure Compiler Closure Compiler是Google公司公布的一款JS压缩工具，和YUICompressor相比，它的压缩率稍微高点，只是稍微，但对代码的准确率要求更高点。这里有一篇LifeSinger整理的《Closure Compiler vs YUICompressor》，讲述了两者的异同，可以做为选择的一个参考。 Closure Compiler使用的命令行代码如下： java -jar compiler.jar --js hello.js --js_output_file hello-compiled.js Closure Compiler还不仅提供了一个网络版可以直接在网页上压缩，而且还开放了API，你可以用HTML、Python或者其它语言文件调用这个API来压缩JS文件。 Packer &#8230; <a href="http://julabs.me/blog/soft/tools-for-javascript-compressor/">继续阅读 <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>JavaScript压缩工具很多，常用的可能就是<a href="http://developer.yahoo.com/yui/compressor/" target="_blank">YUICompressor</a>、<a href="http://code.google.com/intl/zh-CN/closure/compiler/" target="_blank">Closure Compiler</a>、<a href="http://dean.edwards.name/download/#packer" target="_blank">Packer</a>，但我最常用的还是<a href="http://developer.yahoo.com/yui/compressor/" target="_blank">YUICompressor</a>。</p>
<h4><a href="http://developer.yahoo.com/yui/compressor/" target="_blank">YUICompressor</a></h4>
<p><a href="http://developer.yahoo.com/yui/compressor/" target="_blank">YUICompressor</a>是建立在<a href="http://www.mozilla.org/rhino/" target="_blank">rhino interpreter</a>基础上的，所以它的特点就是<strong>安全</strong>。<a href="http://developer.yahoo.com/yui/compressor/" target="_blank">YUICompressor</a>是用<a href="http://www.java.com/zh_CN/" target="_blank">Java</a>编写的，要运行它首先要配置好<a href="http://www.java.com/zh_CN/" target="_blank">Java</a>环境。<a href="http://developer.yahoo.com/yui/compressor/" target="_blank">YUICompressor</a>的压缩内容如下：</p>
<ul>
<li>移除注释</li>
<li>移除额外的空格</li>
<li>细微优化</li>
<li>标识符替换（Identifier Replacement）</li>
</ul>
<p>使用<a href="http://developer.yahoo.com/yui/compressor/" target="_blank">YUICompressor</a>的命令行代码如下：</p>
<pre><code class="dos">java -jar yuicompressor-x.y.z.jar myfile.js -o myfile-min.js --charset utf-8</code></pre>
<p><a href="http://developer.yahoo.com/yui/compressor/" target="_blank">YUICompressor</a>在压缩时还能够自动检查JS代码是否有错误，如果有错误它会列出错误的行数和原因。更难得的是，它也可以压缩<abbr title="Cascading Style Sheets">CSS</abbr>文件，对于前端人员简直就是一把多功能的瑞士军刀。</p>
<p><a href="http://ued.taobao.com/" target="_blank">淘宝UED部</a>把<a href="http://developer.yahoo.com/yui/compressor/" target="_blank">YUICompressor</a>封装成了<a href="http://lifesinger.org/blog/2009/02/tbcompressor-242/" target="_blank">TBCompressor</a>，这里有篇<a href="http://julabs.me/blog/soft/tbcompressor-intro/" target="_blank">《TBCompressor介绍》</a>，使用<a href="http://lifesinger.org/blog/2009/02/tbcompressor-242/" target="_blank">TBCompressor</a>更加简单快捷。</p>
<h4><a href="http://code.google.com/intl/zh-CN/closure/compiler/" target="_blank">Closure Compiler</a></h4>
<p><a href="http://code.google.com/intl/zh-CN/closure/compiler/" target="_blank">Closure Compiler</a>是Google公司公布的一款JS压缩工具，和<a href="http://developer.yahoo.com/yui/compressor/" target="_blank">YUICompressor</a>相比，它的压缩率稍微高点，只是稍微，但对代码的准确率要求更高点。这里有一篇<a href="http://lifesinger.org/blog/" target="_blank">LifeSinger</a>整理的<a href="http://www.slideshare.net/lifesinger/closure-compiler-vs-yuicompressor" target="_blank">《Closure Compiler vs YUICompressor》</a>，讲述了两者的异同，可以做为选择的一个参考。</p>
<p><a href="http://code.google.com/intl/zh-CN/closure/compiler/" target="_blank">Closure Compiler</a>使用的命令行代码如下：</p>
<pre><code class="dos">java -jar compiler.jar --js hello.js --js_output_file hello-compiled.js</code></pre>
<p><a href="http://code.google.com/intl/zh-CN/closure/compiler/" target="_blank">Closure Compiler</a>还不仅提供了一个<a href="http://closure-compiler.appspot.com/home" target="_blank">网络版</a>可以直接在网页上压缩，而且还开放了<a href="http://code.google.com/intl/zh-CN/closure/compiler/docs/api-tutorial1.html" target="_blank">API</a>，你可以用HTML、Python或者其它语言文件调用这个API来压缩JS文件。</p>
<h4><a href="http://dean.edwards.name/download/#packer" target="_blank">Packer</a></h4>
<p><a href="http://dean.edwards.name/download/#packer" target="_blank">Packer</a>是目前压缩率最高的JavaScript压缩工具，由<a href="http://dean.edwards.name/" target="_blank">Dean Edwards</a>创建的。压缩后的JavaScript文件相当于一个ZIP文件，在执行的时候能够自动解压。不过带来的副作用就是对于编写不严格的代码，压缩时会出错，可以在压缩前用<a href="http://www.jslint.com/" target="_blank">JSMin</a>检查下。虽然<a href="http://dean.edwards.name/download/#packer" target="_blank">Packer</a>压缩后的代码在执行时先要自解压下，会降低执行效率，但对于大型文件来说，<a href="http://dean.edwards.name/download/#packer" target="_blank">Packer</a>的压缩率通常能达到50%，因而能加快下载速度。</p>
<p><a href="http://dean.edwards.name/download/#packer" target="_blank">Packer</a>不仅有<a href="http://dean.edwards.name/packer/" target="_blank">网页版</a>，还有<a href="http://dean.edwards.name/download/#packer" target="_blank">.NET、perl和PHP版</a>。</p>
]]></content:encoded>
			<wfw:commentRss>http://julabs.me/blog/soft/tools-for-javascript-compressor/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>动态载入JavaScript以及它的load事件</title>
		<link>http://julabs.me/blog/front/dynamic-script-loading/</link>
		<comments>http://julabs.me/blog/front/dynamic-script-loading/#comments</comments>
		<pubDate>Tue, 24 Aug 2010 06:54:29 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[前端]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[js]]></category>
		<category><![CDATA[load]]></category>

		<guid isPermaLink="false">http://julabs.me/blog/?p=256</guid>
		<description><![CDATA[动态载入JavaScript 动态载入JavaScript非常简单，代码演示如下： var head= document.getElementsByTagName('head')[0]; var script= document.createElement('script'); script.type= 'text/javascript'; script.src= 'test.js'; head.appendChild(script); 侦测JavaScript是否载入 我们常常用JavaScript来给其它元素添加load事件，但如果给一个script自身添加load事件还真不是一件容易的事。对于非IE的高级浏览器来说和一般元素添加事件方法是一样的，代码演示如下： script.onload=function(){ // do something }; 但对于IE来说则要复杂一点，不能直使用onload，而要使用onreadystatechange事件，通过onreadystatechange事件来判断script元素的readyState属性是否等于complete或者loaded，从而来确认script元素是否已经载入。代码演示如下： script.onreadystatechange=function(){ if(this.readyState == 'loaded' &#124;&#124; this.readyState == 'complete'){ // do something } }; readyState具有以下几个状态值： 0 : uninitialized 1 : &#8230; <a href="http://julabs.me/blog/front/dynamic-script-loading/">继续阅读 <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<h4>动态载入JavaScript</h4>
<p>动态载入<strong>JavaScript</strong>非常简单，代码演示如下：</p>
<pre><code class="javascript">var head= document.getElementsByTagName('head')[0];
var script= document.createElement('script');
script.type= 'text/javascript';
script.src= 'test.js';
head.appendChild(script);
</code></pre>
<h4>侦测JavaScript是否载入</h4>
<p>我们常常用<strong>JavaScript</strong>来给其它元素添加<strong>load</strong>事件，但如果给一个<strong>script</strong>自身添加<strong>load</strong>事件还真不是一件容易的事。对于非<abbr title="Internet Explorer">IE</abbr>的高级浏览器来说和一般元素添加事件方法是一样的，代码演示如下：</p>
<pre><code class="javascript">script.onload=function(){
	// do something
};
</code></pre>
<p>但对于<abbr title="Internet Explorer">IE</abbr>来说则要复杂一点，不能直使用<strong>onload</strong>，而要使用<strong>onreadystatechange</strong>事件，通过<strong>onreadystatechange</strong>事件来判断<strong>script</strong>元素的<strong>readyState</strong>属性是否等于<strong>complete</strong>或者<strong>loaded</strong>，从而来确认<strong>script</strong>元素是否已经载入。代码演示如下：</p>
<pre><code class="javascript">script.onreadystatechange=function(){
	if(this.readyState == 'loaded' || this.readyState == 'complete'){
		// do something
	}
};
</code></pre>
<p><strong>readyState</strong>具有以下几个状态值：</p>
<ol>
<li>0 : uninitialized</li>
<li>1 : loading</li>
<li>2 : loaded</li>
<li>3 : interactive</li>
<li>4 : complete</li>
</ol>
<p><span id="more-256"></span></p>
<p>注意：在<abbr title="Internet Explorer">IE</abbr>中<strong>complete</strong>或者<strong>loaded</strong>值是不会一起出现的，<abbr title="Internet Explorer">IE</abbr>中会忽略一些状态，所以只需要判断它俩中的一个就可以了。</p>
<h4>对于JavaScript不存在的处理</h4>
<p>如果动态载入的<strong>JavaScript</strong>文件不存在的话，非<abbr title="Internet Explorer">IE</abbr>浏览器会一直请求。在<abbr title="Internet Explorer 6">IE6</abbr>、<abbr title="Internet Explorer 7">IE7</abbr>中，<strong>script</strong>的属性值<strong>readyState</strong>会返回一个<strong>loading</strong>值，但有时候延迟久了会返回一个<strong>loaded</strong>值。而在<abbr title="Internet Explorer 8">IE8</abbr>中，<strong>script</strong>的属性值<strong>readyState</strong>仍然会返回一个<strong>complete</strong>，这个很奇怪。</p>
<h4>最终方案</h4>
<p>这里根据<a href="http://jquery.com/" target="_blank">jQuery</a>里面的代码修改了下，增加了载入错误的回调功能。代码演示如下：</p>
<pre><code class="javascript">/**
 * 动态载入 javascript 脚本
 * @author &lt;a href="mailto:jon.ju@msn.com"&gt;Jon&lt;/a&gt;
 * @param {Object} options 选项
 * @param {String} options.url 脚本的 url 地址
 * @param {Function} options.callback 脚本完成载入后回调的函数
 * @param {Function} options.error 脚本没有按时载入时回调的函数
 * @param {Number} options.time 请求超时时间,默认为 5 秒
 * @param {String} options.charset 脚本的编码
 */
function insertScript(options){
	var head = document.getElementsByTagName("head")[0] || document.documentElement,
	script = document.createElement("script");
	script.src = options.url;
	var done=false, // 是否完成脚本载入的标识
	timer; // 超时时间
	if (options.charset) {
		script.charset = options.charset;
	}

	script.onload = script.onreadystatechange = function() {

		if ( !done &#038;&#038; (!this.readyState ||
				this.readyState === "loaded" || this.readyState === "complete") ) {
			done = true;
			// 如果有计时器，去除
			if(timer)clearTimeout(timer);
			if(options.callback)options.callback.call();

			// 防止 IE 下的内存泄漏
			script.onload = script.onreadystatechange = null;
			if ( head &#038;&#038; script.parentNode ) {
				head.removeChild( script );
			}

		}
	};

	// 如果有错误回调函数，则超过一定时间就去除 script 的相关设置
	if(options.error){
		timer = setTimeout(function(){
			// 如果还没有完成
			if(!done){
				script.onload = script.onreadystatechange = null;
				if ( head &#038;&#038; script.parentNode ) {
					head.removeChild( script );
				}
				if(options.error){
					options.error.call();
				}
			}
		},options.time || 5000);
	}

	head.appendChild(script);

}
</code></pre>
<p>假设有个在动态载入的<strong>test.js</strong>文件，里面的代码是这样的：</p>
<pre><code class="javascript">var myVar = 'OK';
</code></pre>
<p>载入代码为：</p>
<pre><code class="javascript">insertScript({
	'url':'test.js',
	'callback':function(){
		// IE 在文件不存在时也会触发 callback 函数，
		// 所以在这里要加个判断
		try{
			alert(myVar);
		}catch(e){
			alert('error');
		}
	},
	'error':function(){
		alert('error');
	},
	'time':1000
});
</code></pre>
<p>如果<strong>test.js</strong>存在，则会<strong>alert</strong>出“<strong>OK</strong>”，如果文件不存在<abbr title="Internet Explorer 8">IE8</abbr>会立即<strong>alert</strong>出“<strong>error</strong>”，而其它常用浏览器过1秒后会<strong>alert</strong>出“<strong>error</strong>”。</p>
]]></content:encoded>
			<wfw:commentRss>http://julabs.me/blog/front/dynamic-script-loading/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>JavaScript面向对象编程中私有成员、静态成员的实现</title>
		<link>http://julabs.me/blog/front/private-static-in-javascript-oop/</link>
		<comments>http://julabs.me/blog/front/private-static-in-javascript-oop/#comments</comments>
		<pubDate>Wed, 19 May 2010 14:23:30 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[前端]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[js]]></category>
		<category><![CDATA[oop]]></category>
		<category><![CDATA[private]]></category>
		<category><![CDATA[static]]></category>

		<guid isPermaLink="false">http://julabs.me/blog/?p=201</guid>
		<description><![CDATA[JavaScript面向对象编程中私有成员、静态成员的实现要比Java、ActionScript、Python要复杂的多，现在摘抄一些《JavaScript设计模式》中的代码来做演示。 私有属性和方法 var Book = function(newName){ // 私有属性 var name; // 私有方法 function checkName(name){ // ... } // 特权方法 this.getName = function(){ return name; }; // 特权方法 this.setName = function(newName){ name = newName &#124;&#124; 'No Name'; }; // 构造代码 this.setName(newName); &#8230; <a href="http://julabs.me/blog/front/private-static-in-javascript-oop/">继续阅读 <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><strong>JavaScript</strong>面向对象编程中私有成员、静态成员的实现要比<a href="http://www.java.com/" target="_blank">Java</a>、<a href="http://www.adobe.com/devnet/actionscript/" target="_blank">ActionScript</a>、<a href="http://www.python.org/" target="_blank">Python</a>要复杂的多，现在摘抄一些<a href="http://book.douban.com/subject/3329540/" target="_blank">《JavaScript设计模式》</a>中的代码来做演示。</p>
<h4>私有属性和方法</h4>
<pre><code class="javascript">var Book = function(newName){
    // 私有属性
    var name;

    // 私有方法
    function checkName(name){
        // ...
    }

    // 特权方法
    this.getName = function(){
        return name;
    };

    // 特权方法
    this.setName = function(newName){
        name = newName || 'No Name';
    };

    // 构造代码
    this.setName(newName);

};

var book01 = new Book('name01');
console.log(book01.getName()); // 输出 'name01'
book01.setName('newName01');
console.log(book01.getName()); // 输出 'newName01'
</code></pre>
<p>在本例中用<code>var</code>声明私有变量，这意味着它们只存在于<strong>Book</strong>构造器，<code>checkName</code>函数也是用同样的方法声明的，因此成了一个私有属性。</p>
<p>要想访问这些私有属性和方法的函数只需声明在<strong>Book</strong>中即可，这些方法称为<strong>特权方法(privileged method)</strong>，它们是公有方法，为了能够在对象外部访问这些特权函数，它们的前面都要加上关键字<code>this</code>。其它任何不需要直接访问私有属性的方法都可以放在像<code>Book.prototype</code>中声明。</p>
<p><span id="more-201"></span></p>
<h4>静态属性和方法</h4>
<pre><code class="javascript">var Book = (function(){
    // 私有静态属性
    var numOfBook = 0;

    // 构造函数
    var cotr = function(argument){
        // 私有属性
        var name;

        // 私有方法
        function checkName(name){
            // ...
        }

        // 特权方法
        this.getName = function(){
            return name;
        };

        numOfBook++;
    };

    // 特权静态方法
    cotr.getNumOfBook = function(){
        return numOfBook;
    };

    // 返回构造函数
    return cotr;

})();

// 公有静态方法
Book.display = function(){
    // ...
};

var book01 = new Book();
var book02 = new Book();
console.log(Book.getNumOfBook()); // 输出 2

</code></pre>
<p>在这里私有成员和特权成员仍然被声明在构造函数中，但原来的那个构造函数却从一个普通的函数变成了一个内嵌函数，并且被作为包含它的函数的返回值赋给变量<strong>Book</strong>。这就创建了一个闭包，可以把静态的私有成员声明在里面。位于外层函数声明之后的一对空括号很重要，其作用是代码一载入就立即执行这个函数。这个函数的返回值是另一个函数，它被赋给<strong>Book</strong>变量，<strong>Book</strong>因此成了一个构造函数。在实例化<strong>Book</strong>时，所调用的是这个内层函数，外层那个函数只是用于创建一个可以用来存放静态私有成员的闭包。</p>
]]></content:encoded>
			<wfw:commentRss>http://julabs.me/blog/front/private-static-in-javascript-oop/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Spry源码笔记——自动将Document转换成JSON格式</title>
		<link>http://julabs.me/blog/front/decode-document-to-object/</link>
		<comments>http://julabs.me/blog/front/decode-document-to-object/#comments</comments>
		<pubDate>Tue, 02 Feb 2010 05:02:29 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[前端]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[js]]></category>
		<category><![CDATA[json]]></category>
		<category><![CDATA[spry]]></category>
		<category><![CDATA[xml]]></category>

		<guid isPermaLink="false">http://julabs.me/blog/?p=167</guid>
		<description><![CDATA[在运用Ajax中，有很多操作都是将获得的XML文档转换成JSON格式的，方便JavaScript操作。在Adobe Spry源码里发现了有专门进行这种转换的函数，大大减轻了工作量。我把它提取出来，做了一些改动。 首先创建一个函数，用于判断一个节点是否只含有文本内容： /** * 判断该节点是否只包含文本节点 * @param {Object} node 用于判断的 节点 * @return {Boolean} 如果只包含文本内容为 true */ var nodeHasValue = function(node){ if(node){ var child = node.firstChild; if (child &#38;&#38; child.nextSibling === null &#38;&#38; (child.nodeType === 3 /* Node.TEXT_NODE */ &#8230; <a href="http://julabs.me/blog/front/decode-document-to-object/">继续阅读 <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>在运用Ajax中，有很多操作都是将获得的<a href="http://www.w3.org/XML/" target="_blank">XML</a>文档转换成<a href="http://www.json.org/" target="_blank">JSON</a>格式的，方便JavaScript操作。在<a href="http://labs.adobe.com/technologies/spry/home.html" target="_blank">Adobe Spry</a>源码里发现了有专门进行这种转换的函数，大大减轻了工作量。我把它提取出来，做了一些改动。</p>
<p>首先创建一个函数，用于判断一个节点是否只含有文本内容：</p>
<pre><code class="javascript">/**
 * 判断该节点是否只包含文本节点
 * @param {Object} node 用于判断的 节点
 * @return {Boolean} 如果只包含文本内容为 true
 */
var nodeHasValue = function(node){
	if(node){
		var child = node.firstChild;
		if (child &amp;&amp; child.nextSibling === null &amp;&amp; (child.nodeType === 3 /* Node.TEXT_NODE */ || child.nodeType === 4 /* CDATA_SECTION_NODE */))
			return true;
	}
	return false;
}
</code></pre>
<p>下面是<code>nodeToObject</code>函数，是整个功能模块的核心，它的功能是把<strong>节点</strong>（node）转换成<a href="http://www.json.org/" target="_blank">JSON</a>格式：</p>
<pre><code class="javascript">/**
 * 把 Node 转换成 JSON 格式
 * @param {Object} node 用于转换的 节点
 * @requires EYoo.XML.nodeHasValue 判断该节点是否只包含文本节点
 * @return {Object} obj JSON 格式的信息
*/
var nodeToObject = function(node){
	if (!node)
		return null;
	var obj = {};
	// Add all attributes as properties of the object.
	for (var i = 0; i &lt; node.attributes.length; i++){
		var attr = node.attributes[i];
		var attrName = "@" + attr.name;
		obj[attrName] = attr.value;
	}

	var child;
	// 判断该节点是否只包含文本节点
	if(nodeHasValue(node)){
		try{
			child = node.firstChild;
			if (child.nodeType == 3 /* TEXT_NODE */){
				obj[child.nodeName] = child.data;
			}else if (child.nodeType == 4 /* CDATA_SECTION_NODE */){
				obj[child.nodeName] = child.data;
			}
		}catch(e){
			throw(&quot;nodeToObject() exception caught: &quot; + e + &quot;\n&quot;);
		}

	}else{
		// 如果不是文本节点
		child = node.firstChild;
		while(child){
			if (child.nodeType == 1 /* Node.ELEMENT_NODE */){
				var isArray = false;
				var tagName = child.nodeName;

				// 如果已经存在该节点信息了，则转换成 Array 类型
				if(obj[tagName]){
					if(obj[tagName].constructor != Array){
						var curValue = obj[tagName];
						obj[tagName] = new Array;
						obj[tagName].push(curValue);
					}
					isArray = true;
				}
				var childObj = nodeToObject(child);

				if (isArray)
					obj[tagName].push(childObj);
				else
					obj[tagName] = childObj;
			}
			child = child.nextSibling;
		}
	}
	return obj;
}
</code></pre>
<p><span id="more-167"></span></p>
<p>最后就是<code>documentToObject</code>函数，它的功能是把整个<a href="http://www.w3.org/XML/" target="_blank">XML</a>文档转换成<a href="http://www.json.org/" target="_blank">JSON</a>格式：</p>
<pre><code class="javascript">var documentToObject = function(xmlDoc){
	var obj = null;
	if(xmlDoc &amp;&amp; xmlDoc.firstChild){
		var child = xmlDoc.firstChild;
		while(child){
			if(child.nodeType == 1 /* Node.ELEMENT_NODE */){
				obj = {};
				obj[child.nodeName] = nodeToObject(child);
				break;
			}
			child = child.nextSibling;
		}
	}
	return obj;
}
</code></pre>
<p>另外还有一个<code>encodeEntities</code>函数，它的功能是对文本内容进行转义，防止在使用<code>innerHTML</code>方法时会出现错误：</p>
<pre><code class="javascript">var encodeEntities = function(str){
	if (str &amp;&amp; str.search(/[&amp;&lt;&gt;&quot;]/) != -1){
		str = str.replace(/&amp;/g, &quot;&amp;amp;&quot;);
		str = str.replace(/&lt;/g, &quot;&amp;lt;&quot;);
		str = str.replace(/&gt;/g, &quot;&amp;gt;&quot;);
		str = str.replace(/&quot;/g, &quot;&amp;quot;&quot;);
	}
	return str;
}
</code></pre>
]]></content:encoded>
			<wfw:commentRss>http://julabs.me/blog/front/decode-document-to-object/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>《精通JavaScript》笔记——获得JavaScript对象的类型</title>
		<link>http://julabs.me/blog/front/get-constructor-of-object/</link>
		<comments>http://julabs.me/blog/front/get-constructor-of-object/#comments</comments>
		<pubDate>Sat, 30 Jan 2010 16:40:34 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[前端]]></category>
		<category><![CDATA[constructor]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[js]]></category>
		<category><![CDATA[typeof]]></category>

		<guid isPermaLink="false">http://julabs.me/blog/?p=165</guid>
		<description><![CDATA[在JavaScript中获得对象的类型有两个函数：一个是typeof，另一个是constructor。 下面是使用typeof来判断对象类型的用法，它返回一个字符串： var obj = "I'm string!"; alert(typeof obj === 'string'); 而constructor方法会返回一个构造函数： alert(obj.constructor == String); 下面这个表展示了用上述的两种方法对不同类型对象进行类型检查的结果。 变量 typeof变量 变量.构造函数 {an:&#8221;object&#8221;} object Object ["an","array"] object Array function(){} function Function &#8220;a string&#8221; string String 55 number Number true boolean Boolean new User() &#8230; <a href="http://julabs.me/blog/front/get-constructor-of-object/">继续阅读 <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>在JavaScript中获得对象的类型有两个函数：一个是<code>typeof</code>，另一个是<code>constructor</code>。</p>
<p>下面是使用<code>typeof</code>来判断对象类型的用法，它返回一个字符串：</p>
<pre><code class="javascript">
var obj = "I'm string!";
alert(typeof obj === 'string');
</code></pre>
<p>而<code>constructor</code>方法会返回一个构造函数：</p>
<pre><code class="javascript">alert(obj.constructor == String);
</code>
</pre>
<p>下面这个表展示了用上述的两种方法对不同类型对象进行类型检查的结果。</p>
<table border="0" cellpadding="2" cellspacing="0">
<thead>
<tr>
<th>变量</th>
<th>typeof变量</th>
<th>变量.构造函数</th>
</tr>
</thead>
<tbody>
<tr>
<td>{an:&#8221;object&#8221;}</td>
<td>object</td>
<td>Object</td>
</tr>
<tr>
<td>["an","array"]</td>
<td>object</td>
<td>Array</td>
</tr>
<tr>
<td>function(){}</td>
<td>function</td>
<td>Function</td>
</tr>
<tr>
<td>&#8220;a string&#8221;</td>
<td>string</td>
<td>String</td>
</tr>
<tr>
<td>55</td>
<td>number</td>
<td>Number</td>
</tr>
<tr>
<td>true</td>
<td>boolean</td>
<td>Boolean</td>
</tr>
<tr>
<td>new User()</td>
<td>object</td>
<td>User</td>
</tr>
</tbody>
</table>
<p>从这个表看来，把变量的构造函数作为对象类型引用是最不容易犯错的合法类型检查，通过<strong>name</strong>属性就可以获得对象类型的名称。</p>
<pre><code class="javascript">console.log(obj.constructor.name);
</code>
</pre>
]]></content:encoded>
			<wfw:commentRss>http://julabs.me/blog/front/get-constructor-of-object/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

