<?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>简单生活@NET &#187; WEB应用开发</title>
	<atom:link href="http://lee.kometo.com/archives/category/web/feed" rel="self" type="application/rss+xml" />
	<link>http://lee.kometo.com</link>
	<description>正确的判断来自经验，但经验往往来自错误的判断</description>
	<lastBuildDate>Tue, 10 Aug 2010 11:01:45 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>OSGEO4W 在 Win2003 Server X64 的安装</title>
		<link>http://lee.kometo.com/archives/565</link>
		<comments>http://lee.kometo.com/archives/565#comments</comments>
		<pubDate>Fri, 07 May 2010 03:33:43 +0000</pubDate>
		<dc:creator>kometo</dc:creator>
				<category><![CDATA[IT前沿]]></category>
		<category><![CDATA[WEB应用开发]]></category>

		<guid isPermaLink="false">http://lee.kometo.com/?p=565</guid>
		<description><![CDATA[试图在 Win2003 Server X64 R2下安装OSGEO4W，但遇到很多问题，似乎OSGEO4W这这个版本的Windows有兼容性问题。主要表现在安装过程的组件选择部分 Express不能正常安装，会出现没有相应的现象 Advance 安装中组件依赖关系选择和版本选择都会出错，反复手动选择安装，运行出现一些错误：R6034 等等，特别是Mapserver的安装 &#160; 解决方法： 在一台Windows XP下安装OSGeo4W的全部需要的组件，然后复制到Win2003下，注意两个系统下的目录位置要相同 在2003下Reintstall一下Apache &#160; 完成&#8230; 后续关于MapServer的配置 安装的MapServer Itasca Demo Application存在一些问题，需要修改配置 1. D:\OSGeo\apps\mapserv-demo 下的 IMAGEPATH ，&#34;\&#34;和&#8220;/&#34;问题，否则有临时文件读写错误 2.所有涉及的template文件需要增加一行&#8221;&#60;!&#8211; MapServer Template &#8211;&#62;&#8220;放在文件第一行，否则有模板错误提示 3.D:\OSGeo\apache\conf下httpd.conf,&#60;Directory &#34;d:\OSGeo/tmp/ms_tmp/&#34;&#62; 红色部分补上，否则看不到图]]></description>
			<content:encoded><![CDATA[<p>试图在 Win2003 Server X64 R2下安装OSGEO4W，但遇到很多问题，似乎OSGEO4W这这个版本的Windows有兼容性问题。主要表现在安装过程的组件选择部分</p>
<p>Express不能正常安装，会出现没有相应的现象</p>
<p>Advance 安装中组件依赖关系选择和版本选择都会出错，反复手动选择安装，运行出现一些错误：R6034 等等，特别是Mapserver的安装</p>
<p>&nbsp;</p>
<p>解决方法：</p>
<p>在一台Windows XP下安装OSGeo4W的全部需要的组件，然后复制到Win2003下，注意两个系统下的目录位置要相同</p>
<p>在2003下Reintstall一下Apache</p>
<p>&nbsp;</p>
<p>完成&#8230;</p>
<h3>后续关于MapServer的配置</h3>
<p>安装的MapServer Itasca Demo Application存在一些问题，需要修改配置</p>
<p>1. D:\OSGeo\apps\mapserv-demo 下的 IMAGEPATH ，&quot;\&quot;和&ldquo;/&quot;问题，否则有临时文件读写错误</p>
<p>2.所有涉及的template文件需要增加一行&rdquo;&lt;!&#8211; MapServer Template &#8211;&gt;&ldquo;放在文件第一行，否则有模板错误提示</p>
<p>3.D:\OSGeo\apache\conf下httpd.conf,&lt;Directory &quot;d:\OSGeo/tmp<span style="color: rgb(255, 0, 0);">/ms_tmp</span>/&quot;&gt; 红色部分补上，否则看不到图</p>
]]></content:encoded>
			<wfw:commentRss>http://lee.kometo.com/archives/565/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Javascript中的this详解</title>
		<link>http://lee.kometo.com/archives/483</link>
		<comments>http://lee.kometo.com/archives/483#comments</comments>
		<pubDate>Mon, 14 Dec 2009 09:29:19 +0000</pubDate>
		<dc:creator>kometo</dc:creator>
				<category><![CDATA[WEB应用开发]]></category>
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://lee.kometo.com/?p=483</guid>
		<description><![CDATA[*本文代码中使用的 function dump(v,title), 是一个自己写的输出变量描述的函数。 如果你准备在JavaScript中写类，那么你必需对关键字 this 的使用有深刻的理解： 这是JavaScript手册中对 this的简单解释： this:指当前对象。 对于 JScript 的客户版本，如果在其他所有对象的上下文之外使用 this，则它指的是 window 对象。 在全局环境下的 this 通常我们认为，Javascript 不在任何函数，不在任何类中，直接书写运行的代码的环境，称为直接运行环境，或者全局环境。实际上这个环境并不是一个真正意义上全局环境, 运行下面的代码： dump(this,&#39;Global This&#39;); 我们可以得到输出结果： ■ Global This: object &#8211; [object Window] [The window Object] 可以看到，在这个环境下，this 等于 浏览器的原生对象 window ,它是原生类 Window 的实例。 事实上，当我们在浏览器中运行JavaScript代码时，windows 是所有代码的根节点，所有的代码都是存储并挂接于这个节点的，当然多窗口的环境下会有多个window对象。 function Car(){ } dump(Car); dump(window.Car); 输出结果： ■ function function Car() {&#160; &#8230; [...]]]></description>
			<content:encoded><![CDATA[<p><em>*本文代码中使用的 function dump(v,title), 是一个自己写的输出变量描述的函数。</em></p>
<p>如果你准备在JavaScript中写类，那么你必需对关键字 this 的使用有深刻的理解：</p>
<p>这是JavaScript手册中对 this的简单解释：</p>
<blockquote>
<p><strong>this</strong>:指当前对象。</p>
<p>对于 JScript 的客户版本，如果在其他所有对象的上下文之外使用 <b>this</b>，则它指的是 <b>window</b> 对象。</p>
</blockquote>
<h3><span id="more-483"></span><strong>在全局环境下的 this<br />
	</strong></h3>
<p>通常我们认为，Javascript 不在任何函数，不在任何类中，直接书写运行的代码的环境，称为直接运行环境，或者全局环境。实际上这个环境并不是一个真正意义上全局环境,</p>
<p>运行下面的代码：</p>
<pre class="brush:jscript">dump(this,&#39;Global This&#39;);</pre>
<p>我们可以得到输出结果：</p>
<div>
<div style="color: blue;">
<blockquote>
<p><strong>■ <span style="color: red;">Global This:</span> object</strong> &#8211; [object Window]</p>
<div style="padding: 2px 3em; color: green;">[The window Object]</div>
</blockquote></div>
</div>
<p>可以看到，在这个环境下，this 等于 浏览器的原生对象 <strong>window </strong>,它是原生类 <strong>Window</strong> 的实例。</p>
<p>事实上，当我们在浏览器中运行JavaScript代码时，windows 是所有代码的根节点，所有的代码都是存储并挂接于这个节点的，当然多窗口的环境下会有多个window对象。</p>
<pre class="brush:jscript">function Car(){

}
dump(Car);
dump(window.Car);</pre>
<p>输出结果：</p>
<blockquote>
<div>
<div style="color: blue;"><strong>■ function</strong> <span style="color: green;">function Car() {&nbsp; &#8230;</span></div>
</p></div>
<div>
<div style="color: blue;"><strong>■ function</strong> <span style="color: green;">function Car() { &#8230;</span></div>
</p></div>
</blockquote>
<p>可以看到 Car 和 window.Car 是完全相同的东西</p>
<h3><strong>在类中使用 this<br />
	</strong></h3>
<p>现在我们来看看当使用类的时候，this会发生什么样的变化。下面是一段典型的类定义代码，我们来逐步分析：</p>
<pre class="brush:jscript">function Car(color,doors){
    //用构造模式定义属性
    this.color = color;
    this.doors = doors;
    this.dispThis = function(){
    	dump(this,&#39;this&#39;);
    };
    dump(this,&#39;this&#39;);
}

//原型方法
Car.prototype.dispThis2 = function(){
	dump(this,&#39;this&#39;);
};

//静态方法
Car.dispThis3 = function(){
	dump(this,&#39;this&#39;);
};

aCar = new Car(&#39;red&#39;,4);
aCar.dispThis();
aCar.dispThis2();
Car.dispThis3();
Car(&#39;red&#39;,4);
</pre>
<p>输出结果：</p>
<p>&nbsp;</p>
<blockquote>
<div>
<div style="color: blue;">
<p><strong>■ <span style="color: red;">this:</span> object</strong> &#8211; [object Object]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //构造函数 new Car()</p>
<div style="padding: 2px 3em; color: green;">
<div>&#8211; <strong>color</strong> <strong>■ string</strong> <span style="color: green;">red</span></div>
<div>&#8211; <strong>doors</strong> <strong>■ number</strong> <span style="color: green;">4</span></div>
<div>&#8211; <strong>dispThis</strong> <strong>■ function</strong> <span style="color: green;">function () { dump(this, &quot;this&quot;); }&#8230;</span></div>
<div>&#8211; <strong>dispThis2</strong> <strong>■ function</strong> <span style="color: green;">function () { dump(this, &quot;this&quot;); }&#8230;</span></div>
</p></div>
</p></div>
</p></div>
<div>
<div style="color: blue;">
<p><strong>■ <span style="color: red;">this:</span> object</strong> &#8211; [object Object]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //构造方法 aCar.dispThis();</p>
<div style="padding: 2px 3em; color: green;">
<div>&#8211; <strong>color</strong> <strong>■ string</strong> <span style="color: green;">red</span></div>
<div>&#8211; <strong>doors</strong> <strong>■ number</strong> <span style="color: green;">4</span></div>
<div>&#8211; <strong>dispThis</strong> <strong>■ function</strong> <span style="color: green;">function () { dump(this, &quot;this&quot;); }&#8230;</span></div>
<div>&#8211; <strong>dispThis2</strong> <strong>■ function</strong> <span style="color: green;">function () { dump(this, &quot;this&quot;); }&#8230;</span></div>
</p></div>
</p></div>
</p></div>
<div>
<div style="color: blue;">
<p><strong>■ <span style="color: red;">this:</span> object</strong> &#8211; [object Object]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //原型方法 aCar.dispThis2()</p>
<div style="padding: 2px 3em; color: green;">
<div>&#8211; <strong>color</strong> <strong>■ string</strong> <span style="color: green;">red</span></div>
<div>&#8211; <strong>doors</strong> <strong>■ number</strong> <span style="color: green;">4</span></div>
<div>&#8211; <strong>dispThis</strong> <strong>■ function</strong> <span style="color: green;">function () { dump(this, &quot;this&quot;); }&#8230;</span></div>
<div>&#8211; <strong>dispThis2</strong> <strong>■ function</strong> <span style="color: green;">function () { dump(this, &quot;this&quot;); }&#8230;</span></div>
</p></div>
</p></div>
</p></div>
<div>
<div style="color: blue;">&nbsp;</div>
<div style="color: blue;"><strong>■ <span style="color: red;">this:</span> function</strong> <span style="color: green;">function Car(color, doors) { this.co&#8230;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: rgb(0, 255, 255);">&nbsp;&nbsp;</span></span> //静态方法 Car.dispThis3()</div>
<div style="color: blue;">
<div>
<div style="color: blue;">
<p><strong>■ <span style="color: red;">this:</span> object</strong> &#8211; [object Window]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //直接运行构造函数 Car()</p>
<div style="padding: 2px 3em; color: green;">[The window Object]</div>
</p></div>
</p></div>
</p></div>
</p></div>
</blockquote>
<p>&nbsp;</p>
<p>可以看到在构造函数、构造方法、原型方法中的都可以获取到this对象，它们指向同一个实例对象<strong>aCar</strong>，该对象由 <strong>new Car() </strong>语句生成。</p>
<p>在<strong>Car</strong>的静态方法 <strong>Car.dispThis4</strong>（其实就是Car的一个直接的function属性）中，this 就是<strong>Car</strong> 本身，</p>
<p>当不使用new 关键字，而直接运行类的构造函数<strong>Car</strong>（其实现在它就是一个普通函数）时，在函数内部 this 就是当前运行环境的window对象</p>
<p>注意：比较一下 <strong>aCar.dispThis()</strong> 和 静态方法 <strong>Car.dispThis3()</strong> 输出结果就可以发现：<strong>Car</strong> 和 <strong>Car</strong> 生成的对象是2个完全不同的概念；<strong>Car</strong>是一个函数对象，继承与原生的 <strong>Function</strong> ；而<strong>Car</strong>的实例<strong>aCar</strong>则是一个单纯的对象，它继承与JavaScript原生的 <strong>Object </strong></p>
<p>比较一下：</p>
<p style="text-align: center;">&nbsp;</p>
<p>&nbsp;</p>
<table align="center" border="1" cellpadding="1" cellspacing="1" style="width: 400px;">
<tbody>
<tr>
<td bgcolor="#ff6600">&nbsp;</td>
<td bgcolor="#ff6600" style="text-align: center;">代码</td>
<td bgcolor="#ff6600" style="text-align: center;">结果</td>
</tr>
<tr>
<td>1</td>
<td>aCar.dispThis();</td>
<td>this = aCar</td>
</tr>
<tr>
<td>2</td>
<td>aCar.dispThis2();</td>
<td>this = aCar</td>
</tr>
<tr>
<td>3</td>
<td>Car.dispThis3();</td>
<td>this = Car</td>
</tr>
<tr>
<td>4</td>
<td>new Car();</td>
<td>this = aCar</td>
</tr>
<tr>
<td>5</td>
<td>Car();</td>
<td>this = window</td>
</tr>
</tbody>
</table>
<p>通过这个表格特别是1、2、3行，我们可以清晰的得到一个规律：<strong>this 其实就等于调用代码时的调用的节点</strong>，即：aCar. 和 Car. 。这个调用节点也就是参考文档中所提到的<strong>上下文环境</strong>。</p>
<p>那么如何解释4、5的结果呢？</p>
<p>new Car();使用了一个特殊关键字 new ，这个关键字的作用就是生成一个新的对象，并赋值给 this 。所以 this = aCar</p>
<p>Car();没有通过任何节点调用，实际上通过了默认节点window 来调用，通过上一节我们也可以看出 Car 实际上就是 window.Car 。所以 this = window</p>
<h3><strong>总结和结论：</strong></h3>
<p><u><strong>JavaScript中所有的东西都是对象，包括数字、字符、函数以及对象的属性，函数总是存在（挂接）于某个对象中（默认存在于window对象），并通过某个对象调用的。在函数中总是有一个可用的的 this 变量，脚本引擎对 this 的解析是动态的，运行时的；<u><strong>它指向函数被调用时所挂接的对象。</strong></u></strong></u></p>
<p>我们可以通过一系列函数对象来进一步明晰这个过程，这些函数对象我们有时也称之为类的静态方法，实际上类的静态方法本身也是一个类，也是一个对象，明白了这一点，你就可以深刻理解Javascript的对象机制了。</p>
<pre class="brush:jscript">function Car(){
	this.name = &#39;car&#39;;
	e(this);
};

Car.Wheel = function(){
	this.name = &#39;wheel&#39;;
	e(this);

};

Car.Wheel.Size = function(){
	this.name = &#39;wheel.size&#39;;
	e(this);
}

Car();
Car.Wheel();
Car.Wheel.Size();
</pre>
<p>输出结果</p>
<blockquote>
<div style="color: blue;"><strong>■ object</strong> &#8211; [object Window]</div>
<div style="color: blue;"><strong>■ function</strong> <span style="color: green;">function Car() { this.name = &quot;car&quot;; &#8230;</span></div>
<div style="color: blue;"><strong>■ function</strong> <span style="color: green;">function () { this.name = &quot;wheel&quot;; &#8230;</span></div>
</blockquote>
<p>&nbsp;</p>
<table align="center" border="1" cellpadding="1" cellspacing="1" style="width: 400px;">
<tbody>
<tr>
<td bgcolor="#ff6600">&nbsp;</td>
<td bgcolor="#ff6600" style="text-align: center;">代码</td>
<td bgcolor="#ff6600" style="text-align: center;">结果</td>
</tr>
<tr>
<td>1</td>
<td>Car();</td>
<td>this = window</td>
</tr>
<tr>
<td>2</td>
<td>Car.Wheel();</td>
<td>this = Car</td>
</tr>
<tr>
<td>3</td>
<td>Car.Wheel.Size();</td>
<td>this = Car.Wheel</td>
</tr>
</tbody>
</table>
<h3><strong>当 this 遇到事件</strong></h3>
<p>当我们在事件函数中使用到 this 时，this 有时会很不听话，经常会取值为意料之外的对象。先来看一段示例代码：</p>
<p>我们定义一个类的方法函数 Car.prototype.show();</p>
<pre class="brush:jscript">function Car(){
	this.name = &#39;Class Car&#39;;
}

Car.prototype.show = function(){
	echo(&#39;On Car.show&#39;);
	dump(this,&#39;this&#39;);
};

aCar = new Car;
</pre>
<p>然后使用两个按钮的分别用两种方式触发 aCar.show;</p>
<pre class="brush:jscript">&lt;input id=&quot;btn1&quot; type=&quot;button&quot; value=&quot;Press Me call car.show&quot;/&gt;
&lt;input id=&quot;btn2&quot; type=&quot;button&quot; value=&quot;Press Me call car.show #2&quot;/&gt;

&lt;script type=&#39;text/javascript&#39;&gt;
   document.getElementById(&quot;btn1&quot;).onclick = aCar.show;
  &nbsp;document.getElementById(&quot;btn2&quot;).onclick = function(){aCar.show();}
&lt;/script&gt;
</pre>
<p>&nbsp;</p>
<p>输出结果</p>
<blockquote>
<div>//btn1 click</div>
<div>
<div style="color: blue;">
<p><strong>■ <span style="color: red;">this:</span> object</strong> &#8211; [object HTMLInputElement]</p>
<div style="padding: 2px 3em; color: green;">
<div>&#8211; <strong>tagName</strong> <strong>■ string</strong> <span style="color: green;">INPUT</span></div>
<div>&#8211; <strong>value</strong> <strong>■ string</strong> <span style="color: green;">Press Me call car.show</span></div>
<div>&#8211; <strong>id</strong> <strong>■ string</strong> <span style="color: green;">btn1</span></div>
<div>&#8211; <strong>className </strong> <strong>■ string</strong></div>
<div>&#8230;&#8230;.</div>
</p></div>
</p></div>
</p></div>
<div>//btn2 click</div>
<div>
<div style="color: blue;">
<p><strong>■ <span style="color: red;">this:</span> object</strong> &#8211; [object Object]</p>
<div style="padding: 2px 3em; color: green;">
<div>&#8211; <strong>name</strong> <strong>■ string</strong> <span style="color: green;">Class Car</span></div>
<div>&#8211; <strong>show</strong> <strong>■ function</strong> <span style="color: green;">function () { echo(&quot;On Car.show&quot;); &#8230;</span></div>
</p></div>
</p></div>
</p></div>
</blockquote>
<p>&nbsp;</p>
<p>我们看到<strong>btn1</strong>的<strong>click</strong>事件中 <strong>this </strong>的输出结果是 <strong>Input</strong>元素，</p>
<p><strong>btn2</strong>的<strong>Click</strong>事件中，<strong>this </strong>的输出结果是 <strong>aCar</strong>。</p>
<p>为什么会出现这一结果呢？</p>
<p>造成不同的主要原因是事件的绑定方式的不同，我们来看看事件的绑定过程：</p>
<p><strong>btn1</strong>使用<strong> document.getElementById(&quot;btn1&quot;).onclick = aCar.show&nbsp; </strong>这条语句进行了事件绑定。<br />
	我们把 btn1.click 指向（引用）了 aCar.show，当事件触发时 btn1.click 被调用（回调），也就是调用了 aCar.show&nbsp; 的代码；看起来一切正常，唯一需要注意的是： aCar.show&nbsp; 的内部代码不是以节点名称 aCar 来调用的，而是以节点 btn1 来调用的，也就是说此时 show()&nbsp; 的运行时节点是 btn1，那么 <strong>this </strong>也就成为了 <strong>btn1</strong>。</p>
<p><strong>btn2 </strong>使用&nbsp;<strong>document.getElementById(&quot;btn1&quot;).onclick = function(){aCar.show();} </strong>。<br />
	和btn1唯一的区别就是它使用了一个匿名函数把 aCar.show();包裹起来了。就是这样简单一个包裹引起根本性的变化，当事件触发时 btn1.click 被调用（回调），运行代码并不直接是 aCar.show ，而是通过匿名函数又再次调用 aCar.show ；此时调用的节点是 aCar ,所以 this = aCar 。</p>
<p>有些文章用事件函数的复制和引用来解释btn1和btn2结果的不同，这种解释实际是错误的，流于表象的，虽然很多文章还做了很多图来解释&#8230; JavaScript 的所有赋值语句都应该理解为引用，这又是另外一个话题，不扯远了&#8230;</p>
<p>我们来进一步比较不同事件函数绑定方式所带来的 this 的变化：</p>
<pre style="margin-right: -982px;">function Car(){
	this.name = &#39;Class Car&#39;;
}

Car.prototype.show = function(){
	dump(this,&#39;this&#39;);
};

aCar = new Car;

element.onclick = aCar.show;                       // this = element
element.addEventListener(&#39;click&#39;,aCar.show, false) // this = element

element.onclick = function () {aCar.show();}      // this = aCare
lement.attachEvent(&#39;onclick&#39;,aCar.show)           // this = aCare
&lt;element onclick=&quot;aCar.show();&quot;&gt;                  // this = aCare

element.onclick = function () {this.style.color = &#39;#cc0000&#39;;}     //this = element
&lt;element onclick=&quot;this.style.color = &#39;#cc0000&#39;;&quot;&gt;                 //this = element
</pre>
<p><strong><br />
	</strong></p>
<p><strong>总结：</strong><u><strong><u><strong>this 指向函数被调用时所挂接的对象。</strong></u></strong></u><strong>当事件函数被调用时，this 总是等于事件所在的节点，因此我们应该使用匿名函数作为事件函数，并在匿名函数中二次调用可能需要的其它函数。以此来避免可能的 this 混乱。<br />
	</strong></p>
<p>现在我们来看一段示范代码，这是一段典型的既能获取函数本身所在节点，又能获取触发对象的代码模式</p>
<pre style="margin-right: -982px;">function Car(){
	this.name = &#39;Class Car&#39;;
}

Car.prototype.doSomethin = function(obj){
  dump(this,&#39;this&#39;);  //this = aCar
  dump(obj,&#39;obj&#39;);    //obj = element
};

aCar = new Car();

&lt;element onclick=&quot;aCar.doSomething(this)&quot;&gt;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; //方法1
element.onclick = function() {aCar.doSomething(this)}     //方法2
</pre>
<p><strong>在类中进行事件绑定操作<br />
	</strong></p>
<p>当我们在类代码中进行事件绑定操作时，对this的使用会遇到新的困难，我们知道所有的事件函数中 this 都必然等于事件函数所在的对象（即上例中的btn1)，那么我们如何在一个类中书写一段匿名事件函数，并在匿名事件函数中调用当前类的对象呢？</p>
<p>看代码：</p>
<pre style="margin-right: -982px;">&lt;input id=&quot;btn1&quot; type=&quot;button&quot; value=&quot;Press Me call car.show&quot;/&gt;

&lt;script type=&#39;text/javascript&#39;&gt;&lt;!--

function Car(){
	this.name = &#39;Class Car&#39;;
}
Car.prototype.showThis = function(obj){
	dump(this,&#39;this&#39;);
	dump(obj,&#39;obj&#39;);
};
Car.prototype.bind = function(){
	document.getElementById(&quot;btn1&quot;).onclick = function(){ this.showThis(this); };
};

aCar = new Car;
aCar.bind();

--&gt;&lt;/script&gt;
</pre>
<p>如果你看到这里对 this 已经有了深刻的理解，那么就会发现这段代码实际使用的话会出错的，问题就出在这一行代码：</p>
<p style="margin-left: 40px;"><strong>document.getElementById(&quot;btn1&quot;).onclick = function(){this.showThis(this);};<br />
	</strong></p>
<p>这行代码的本身是在aCar.bind中运行，然后这行代码又写了一个匿名函数：<strong>function(){this.showThis(this);} 。</strong>匿名函数中我们希望调用当前对象 aCar 的方法 showThis ,同时又想把事件触发对象btn1 传递给 showThis。我们用了2个 this ，这里的 this 到底应该等于什么呢？两个 this 都应该等于 btn1 ,因为这个匿名函数将会以节点 btn1.click 来运行的。this.showThis 将会无法调用到我们希望的目标 aCar.showThis ；</p>
<p>那么如何改写这段代码，来正确的调用aCar.showThis 呢？似乎目前只有这个方法，使用一个临时变量来传递 this ：</p>
<p style="margin-left: 40px;"><strong>var </strong><span style="color: rgb(255, 0, 0);">_this</span> = this;</p>
<p style="margin-left: 40px;"><strong><strong>document.getElementById(&quot;btn1&quot;).onclick = function(obj){<span style="color: rgb(255, 0, 0);">_this</span>.showThis(obj);};</strong></strong></p>
<p>其实这样代码看起来有点让人难以理解，如果想更深入的解释这段代码，就需要进一步解释JavaScript的编译和解释运行机制，我对此也没有深入的研究，但是可以推测出的原因是：JavaScript的脚本引擎对变量的编译和解释是根据代码书写环境（书写节点）来进行的，而对this 似乎总是根据运行环境（运行节点）来赋值的。</p>
<h3><strong>回调函数和 this 使用的总结</strong></h3>
<p><span style="color: rgb(0, 100, 0);"><strong>关于 this 的使用似乎很让人头晕，特别是当 this 和事件和类混在一起使用的时候，如果你需要一个简单的方法来处理这个，我们可以归纳出几条规则</strong></span></p>
<ol>
<li><span style="color: rgb(0, 100, 0);"><strong>事件处理函数又可以称为回调函数(CallBack Function)，回调函数不仅仅用于界面事件（Click,Moueover等等）的处理，很多异步处理需要大量的回调函数。</strong></span></li>
<li><span style="color: rgb(0, 100, 0);"><strong>总是使用匿名函数作为回调函数，并在匿名函数中再调用其它命名函数，使用 event = function(){ somefunction(); }&nbsp; 的方式，不要使用 event = somefunction 的方式</strong></span></li>
<li><span style="color: rgb(0, 100, 0);"><strong>命名并传递默认参数，同时也可以把回调函数中的 this 传递给其它被调用函数。如：event = function(params){ somefunction(this,params); }</strong></span></li>
<li><span style="color: rgb(0, 100, 0);"><strong>如果在类中书写匿名回调函数，并且需要在函数中调用当前类的当前对象，使用一个临时变量来引用 function(){_this.showThis();};</strong></span></li>
</ol>
<p><strong>最后来看看常见的Jquery的事件绑定方式：</strong></p>
<pre style="margin-right: -982px;">&lt;input id=&quot;btn1&quot; type=&quot;button&quot; value=&quot;Press Me call car.show&quot;/&gt;
&lt;input id=&quot;btn2&quot; type=&quot;button&quot; value=&quot;Press Me call car.show #2&quot;/&gt;

&lt;script type=&#39;text/javascript&#39;&gt;&lt;!--

function Car(){
	this.name = &#39;Class Car&#39;;
}
Car.prototype.show = function(){
	echo(&#39;On Car.show&#39;);
	dump(this,&#39;this&#39;);
};
aCar = new Car;

$(&quot;#btn1&quot;).click(function(){aCar.show()});  //通过匿名函数2次调用 this = aCar
$(&quot;#btn2&quot;).click(aCar.show);                // this = btn2

--&gt;&lt;/script&gt;
</pre>
<p>输出结果</p>
<blockquote>
<div>On Car.show //这个是引用方式 this = aCar</div>
<div>
<div style="color: blue;">
<p><strong>■ <span style="color: red;">this:</span> object</strong> &#8211; [object Object]</p>
<div style="padding: 2px 3em; color: green;">
<div>&#8211; <strong>name</strong> <strong>■ string</strong> <span style="color: green;">Class Car</span></div>
<div>&#8211; <strong>show</strong> <strong>■ function</strong> <span style="color: green;">function () { echo(&quot;On Car.show&quot;); &#8230;</span></div>
</p></div>
</p></div>
</p></div>
<div>On Car.show //这个是复制方式 this = btn2</div>
<div>
<div style="color: blue;">
<p><strong>■ <span style="color: red;">this:</span> object</strong> &#8211; [object HTMLInputElement]&nbsp;</p>
<div style="padding: 2px 3em; color: green;">
<div>&#8211; <strong>tagName</strong> <strong>■ string</strong> <span style="color: green;">INPUT</span></div>
<div>&#8211; <strong>value</strong> <strong>■ string</strong> <span style="color: green;">Press Me call car.show #2</span></div>
<div>&#8211; <strong>id</strong> <strong>■ string</strong> <span style="color: green;">btn2</span></div>
<div>&#8211; <strong>className </strong> <strong>■ string</strong></div>
<div>&#8230;&#8230;.</div>
</p></div>
</p></div>
</p></div>
</blockquote>
]]></content:encoded>
			<wfw:commentRss>http://lee.kometo.com/archives/483/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Javascirpt IE中的HTMLElement</title>
		<link>http://lee.kometo.com/archives/487</link>
		<comments>http://lee.kometo.com/archives/487#comments</comments>
		<pubDate>Mon, 14 Dec 2009 03:08:53 +0000</pubDate>
		<dc:creator>kometo</dc:creator>
				<category><![CDATA[WEB应用开发]]></category>
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://lee.kometo.com/?p=487</guid>
		<description><![CDATA[在DOM标准中，每个HTML元素都是继承自HTMLElement。这是DOM的继承关系树： 这里的Node,HTMLElement,HTMLAnchorElement其实就是HTML元素对象的类声明，我们可以通过修改这些类的原型来修改所有相关的HTML元素特性。 但是，HTMLElement和Node在IE中是虽然存在的，但是IE屏蔽了它，我们是无法访问到它的。 所有的Node实例有个标准属性 nodeType,有时它可以帮助我们判断一个NODE的属性 &#160; nodeType values chart 列表 Returned integer Node type Constant 1 ELEMENT_NODE 2 ATTRIBUTE_NODE 3 TEXT_NODE 4 CDATA_SECTION_NODE 5 ENTITY_REFERENCE_NODE 6 ENTITY_NODE 7 PROCESSING_INSTRUCTION_NODE 8 COMMENT_NODE 9 DOCUMENT_NODE 10 DOCUMENT_TYPE_NODE 11 DOCUMENT_FRAGMENT_NODE 12` NOTATION_NODE 比如判断一个对象是否为 HTMLElement的实例： Oobj instanceof HTMLElement; //这行代码在IE中会报错的 Oobj .nodeType == Node.ELEMENT_NODE; //这行代码在IE中会报错的 Oobj .nodeType == 1; //Node.ELEMENT_NODE=1 [...]]]></description>
			<content:encoded><![CDATA[<p>在DOM标准中，每个HTML元素都是继承自HTMLElement。这是DOM的继承关系树：</p>
<p style="text-align: center;"><a href="http://lee.kometo.com/wp-content/uploads/2009/12/200981518213488.jpg"><img alt="200981518213488" class="aligncenter size-full wp-image-488" height="293" src="http://lee.kometo.com/wp-content/uploads/2009/12/200981518213488.jpg" title="200981518213488" width="308" /></a></p>
<p><span id="more-487"></span></p>
<p>这里的Node,HTMLElement,HTMLAnchorElement其实就是HTML元素对象的类声明，我们可以通过修改这些类的原型来修改所有相关的HTML元素特性。</p>
<p>但是，HTMLElement和Node在IE中是虽然存在的，但是IE屏蔽了它，我们是无法访问到它的。</p>
<p>所有的Node实例有个标准属性 nodeType,有时它可以帮助我们判断一个NODE的属性</p>
<p>&nbsp;</p>
<h3 jquery1260758960156="2">nodeType values chart 列表</h3>
<table align="center" border="1" cellpadding="2" cellspacing="0" style="width: 200px;" width="100%">
<tbody>
<tr>
<th class="captions" valign="top" width="20%">Returned integer</th>
<th class="captions" width="80%">Node type Constant</th>
</tr>
<tr>
<td height="27" valign="top" width="20%">1</td>
<td height="27" width="80%">ELEMENT_NODE</td>
</tr>
<tr>
<td valign="top" width="20%">2</td>
<td width="80%">ATTRIBUTE_NODE</td>
</tr>
<tr>
<td valign="top" width="20%">3</td>
<td width="80%">TEXT_NODE</td>
</tr>
<tr>
<td valign="top" width="20%">4</td>
<td width="80%">CDATA_SECTION_NODE</td>
</tr>
<tr>
<td valign="top" width="20%">5</td>
<td width="80%">ENTITY_REFERENCE_NODE</td>
</tr>
<tr>
<td valign="top" width="20%">6</td>
<td width="80%">ENTITY_NODE</td>
</tr>
<tr>
<td valign="top" width="20%">7</td>
<td width="80%">PROCESSING_INSTRUCTION_NODE</td>
</tr>
<tr>
<td valign="top" width="20%">8</td>
<td width="80%">COMMENT_NODE</td>
</tr>
<tr>
<td valign="top" width="20%">9</td>
<td width="80%">DOCUMENT_NODE</td>
</tr>
<tr>
<td valign="top" width="20%">10</td>
<td width="80%">DOCUMENT_TYPE_NODE</td>
</tr>
<tr>
<td valign="top" width="20%">11</td>
<td width="80%">DOCUMENT_FRAGMENT_NODE</td>
</tr>
<tr>
<td valign="top" width="20%">12`</td>
<td width="80%">NOTATION_NODE</td>
</tr>
</tbody>
</table>
<p>比如判断一个对象是否为 HTMLElement的实例：</p>
<pre>Oobj instanceof HTMLElement;         //这行代码在IE中会报错的
Oobj .nodeType == Node.ELEMENT_NODE; //这行代码在IE中会报错的
Oobj .nodeType == 1;                 //Node.ELEMENT_NODE=1 在IE中只能直接使用数字

//一段完整判断函数
function isElement(Oobj ){
    return !!(Oobj &amp;&amp; Oobj.nodeType == 1);
} </pre>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>参考：</p>
<p>DOM对象参考手册 http://www.navioo.com/DOMReference/HTML/reference/api/htmldom2.index.php</p>
<p>这个站关于JavaScript的参考资料很好，很强大 http://www.navioo.com</p>
]]></content:encoded>
			<wfw:commentRss>http://lee.kometo.com/archives/487/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Javascript类的原型对象和继承</title>
		<link>http://lee.kometo.com/archives/480</link>
		<comments>http://lee.kometo.com/archives/480#comments</comments>
		<pubDate>Sat, 12 Dec 2009 16:44:37 +0000</pubDate>
		<dc:creator>kometo</dc:creator>
				<category><![CDATA[WEB应用开发]]></category>

		<guid isPermaLink="false">http://lee.kometo.com/?p=480</guid>
		<description><![CDATA[基本对象分析 JavaScript中所有的东西都是对象，包括函数、字符、数字等等等。但是JavaScript没有Class这个概念。 JavaScript使用Function来模拟类，任何一个function都有一个对应的prototype对象来存储和扩展这个function的定义，也就是说原型对象是关联于函数的 我们计划使用new关键字来调用并生成新对象的函数，我们称为&#8220;构造函数&#8221; 一个基本的函数分析 function Car(){ color = &#39;red&#39;; }; echo(Car); echo(Car.constructor); echo(Car.prototype); echo(Car.prototype.constructor); 输出结果 function Car() { color = &#34;red&#34;; } function Function() { [native code] } [object Object] function Car() { color = &#34;red&#34;; } Car本身是一个函数 它的constructor是原生对象（Native Function） 在函数Car定义解析的同时，会系统生成一个对象 Car.prototype，它将会是所有由Car生成(new)的实例对象的原型对象，注意它是对象，这不同于常见的Class概念。默认的原型对象没有任何属性 Car的原型对象的Constructor就是Car自己，这也说明了原型对象是在函数定义的同时产生的。 原型对象 函数的原型对象是在脚本引擎解析每个函数代码时自动生成的，而不是执行时才生成 //function Car 是显式定义的，Car.prototype已经在代码解析时自动生成了，此时可以访问 echo(Car.prototype); function Car(){}; //function Plan 是赋值定义的，Plan.prototype没有自动生成了，此时不能访问 [...]]]></description>
			<content:encoded><![CDATA[<p><strong>基本对象分析</strong></p>
<p>JavaScript中所有的东西都是对象，包括函数、字符、数字等等等。但是JavaScript没有Class这个概念。</p>
<p>JavaScript使用Function来模拟类，任何一个function都有一个对应的prototype对象来存储和扩展这个function的定义，也就是说原型对象是关联于函数的</p>
<p>我们计划使用new关键字来调用并生成新对象的函数，我们称为&ldquo;构造函数&rdquo;</p>
<p>一个基本的函数分析</p>
<pre class="brush:jscript">function Car(){
	color = &#39;red&#39;;
};

echo(Car);
echo(Car.constructor);
echo(Car.prototype);
echo(Car.prototype.constructor);
</pre>
<p>输出结果<span id="more-480"></span></p>
<blockquote>
<div>function Car() { color = &quot;red&quot;; }</div>
<div>function Function() { [native code] }</div>
<div>[object Object]</div>
<div>function Car() { color = &quot;red&quot;; }</div>
</blockquote>
<ol>
<li>Car本身是一个函数</li>
<li>它的constructor是原生对象（Native Function）</li>
<li>在函数Car定义解析的同时，会系统生成一个对象 Car.prototype，它将会是所有由Car生成(new)的实例对象的原型对象，注意它是对象，这不同于常见的Class概念。默认的原型对象没有任何属性</li>
<li>Car的原型对象的Constructor就是Car自己，这也说明了原型对象是在函数定义的同时产生的。</li>
</ol>
<p><strong>原型对象<br />
	</strong></p>
<p>函数的原型对象是在脚本引擎解析每个函数代码时自动生成的，而不是执行时才生成</p>
<pre class="brush:jscript">//function Car 是显式定义的，Car.prototype已经在代码解析时自动生成了，此时可以访问
echo(Car.prototype);
function Car(){};

//function Plan 是赋值定义的，Plan.prototype没有自动生成了，此时不能访问
echo(Plan.prototype);
Plan = function(){};
//现在才可以访问
echo(Plan.prototype); </pre>
<p>原型对象实际的工作方式是一种链式查找，脚本运行时，脚本引擎首先在当前实例对象中查找指定的属性，如果有就直接使用，如果没有就到原型对象中找，如果原型对象也没有，就到原型对象的原型对象中查找，这是一个递归的查找链。所有的JavaScript对象的查找链最终都会归结到原生函数Object的原型对象中去。</p>
<pre class="brush:jscript">function Car(){
	this.color = &#39;red&#39;;
};

Car.prototype.color = &#39;blue&#39;;
Car.prototype.doors = 4;
Object.prototype.wheels = 4;

aCar = new Car;
echo(aCar.color);
echo(aCar.doors);
echo(aCar.wheels);</pre>
<p>&nbsp;</p>
<p>输出结果：</p>
<blockquote>
<div>red &nbsp;//注意：这里构造函数中定义的属性color覆盖了原型中的color定义</div>
<div>4 //从原型中查找到了doors</div>
<div>4 //从根原型中查找到了wheels</div>
</blockquote>
<p>&nbsp;</p>
<p>实例对象的原型对象关系链是有脚本引擎内部维护的，我们不能操作和修改它，但是可以通过定义和修改构造函数的prototype属性来影响的以后生成(new)的实例对象的原型对象，而JavaScript的继承关系正是通过这一方式来模拟的。</p>
<p>&nbsp;</p>
<p><strong>类的继承<br />
	</strong></p>
<p>JavaScript所有原生函数(Function,Array..)的Prototype对象指针是只读的，不能修改。你可以改变原型的内容，但不能改变原型对象本身。</p>
<p>而非原生函数的的原型对象是可以修改，如果把一个函数（A）的原型定义(prototype)指向另一个函数函数（B）的实例，这样可以就模拟出A继承B的效果</p>
<p>其实际效果是：把B的原型对象插入到了A的实例对象的原型链中去：</p>
<p style="text-align: center;"><strong>new A &gt; A.prototype &gt; B.prototype &gt; &#8230;. &gt; Object.prototype<br />
	</strong></p>
<pre class="brush:jscript">//这样的代码是不能执行的
Array.prototype = new String(&#39;&#39;);

function Car(){}
function RaceCar(){}
//RaceCar 现在继承了 Car 的定义
RaceCar.prototype = new Car;
</pre>
<p>考虑到修改函数原型对象时可能会造成修改前的原型定义丢失，所有应该仅可能早的指定原型对象。</p>
<p>同时你也许需要修改新原型对象的constructor，使其指向当前构造函数，典型的继承关系处理代码如下：</p>
<pre class="brush:jscript">function Car(){
	Car.prototype.color = &#39;blue&#39;;
	this.doors = 4;
}

function RaceCar(){
	RaceCar.prototype.color = &#39;red&#39;;
	this.doors = 2;
}
RaceCar.prototype = new Car; //RaceCar 现在继承了 Car 的定义
RaceCar.prototype.constructor = RaceCar;  //修改constructor

aCar = new RaceCar();

Car.prototype.wheels = 4;

echo(aCar.color);
echo(aCar.wheels);
</pre>
<p>输出结果为：</p>
<blockquote>
<div>red</div>
<div>4</div>
</blockquote>
<p>11</p>
<p>建模结构图</p>
<p>我们使用一段代码及其对应的建模结构图来进一步说明JavaScript的继承处理方式：</p>
<p>代码：</p>
<pre class="brush:jscript">function A(){

}

B.prototype = new A;
B.prototype.constructor = B;

function B(){

}
</pre>
<p>结构图：</p>
<p style="text-align: center;">&nbsp;</p>
<p style="text-align: center;"><img align="middle" alt="prototype" class="aligncenter size-full wp-image-484" height="284" src="http://lee.kometo.com/wp-content/uploads/2009/12/prototype.gif" title="prototype" width="425" /></p>
<p>&nbsp;</p>
<p>参考：http://mckoss.com/jscript/object.htm</p>
]]></content:encoded>
			<wfw:commentRss>http://lee.kometo.com/archives/480/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Javascript-类的基本定义方式</title>
		<link>http://lee.kometo.com/archives/439</link>
		<comments>http://lee.kometo.com/archives/439#comments</comments>
		<pubDate>Sat, 12 Dec 2009 11:28:11 +0000</pubDate>
		<dc:creator>kometo</dc:creator>
				<category><![CDATA[WEB应用开发]]></category>
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://lee.kometo.com/?p=439</guid>
		<description><![CDATA[经典模式 直接生成对象实例，并操作实例 //定义 var aCar = new Object(); aCar.color = &#34;red&#34;; aCar.doors = 4; aCar.showColor = function() {} //调用 aCar.showColor(); 工厂模式 其实就把上面的代码用过函数封装一下 //定义 function createCar(color,doors){ var aCar = new Object(); aCar.color = color; aCar.doors = doors; aCar.showColor = function() {alert(this.color);}; return aCar; } //调用 bCar = createCar(&#39;red&#39;,4); bCar.showColor(); 混合工厂模式 函数名直接用类名，然后用了关键字new，其实这样写仅仅是好看一些，和上面的工厂方法没有本质区别。 //定义 function car(color,doors){ var aCar [...]]]></description>
			<content:encoded><![CDATA[<p><strong>经典模式</strong></p>
<p>直接生成对象实例，并操作实例</p>
<pre class="brush:jscript">//定义
var aCar = new Object();
aCar.color = &quot;red&quot;;
aCar.doors = 4;
aCar.showColor = function() {}
//调用
aCar.showColor();
</pre>
<p><span id="more-439"></span></p>
<p><strong>工厂模式<br />
	</strong></p>
<p>其实就把上面的代码用过函数封装一下</p>
<pre class="brush:jscript">//定义
function createCar(color,doors){
  var aCar = new Object();
  aCar.color = color;
  aCar.doors = doors;
  aCar.showColor = function() {alert(this.color);};
  return aCar;
}
//调用
bCar = createCar(&#39;red&#39;,4);
bCar.showColor();
</pre>
<p><strong>混合工厂模式<br />
	</strong></p>
<p>函数名直接用类名，然后用了关键字new，其实这样写仅仅是好看一些，和上面的工厂方法没有本质区别。</p>
<pre class="brush:jscript">//定义
function car(color,doors){
  var aCar = new Object();
  aCar.color = color;
  aCar.doors = doors;
  aCar.showColor = function() {alert(this.color);};
  return aCar;
}
//调用
bCar = new car(&#39;red&#39;,4);
bCar.showColor();
</pre>
<p><strong>构造模式<br />
	</strong></p>
<pre class="brush:jscript">//定义
function car(color,doors){
  this.color = color;
  this.doors = doors;
  this.showColor = function() {alert(this.color);};
}
//调用
bCar = new car(&#39;red&#39;,4);
bCar.showColor();
</pre>
<p>&nbsp;</p>
<p>和上面相比，少了2句：<span style="color: rgb(0, 128, 0);"><strong>var aCar = new Object() </strong></span>和 <strong><span style="color: rgb(0, 128, 0);">return aCar </span></strong>。实际上关键字 <strong><span style="color: rgb(0, 128, 0);">new </span></strong>默认执行了一个操作：<strong><span style="color: rgb(0, 128, 0);">this = new Object() </span></strong>，而this会作为构造函数的默认返回值。</p>
<p>&nbsp;</p>
<p><strong>原型模式<br />
	</strong></p>
<pre class="brush:jscript">//定义
function car(){}
car.prototype.color = &#39;red&#39;;
car.prototype.doors = 4;
car.prototype.showColor = function() {alert(this.color);};

//调用
bCar = new car();
bCar.showColor();
</pre>
<p>&nbsp;</p>
<p><strong>动态原型模式<br />
	</strong></p>
<p>定义并判断类的静态属性_<strong>initialized</strong>，在构造函数内部动态定义修改类原型。</p>
<p>&nbsp;</p>
<pre class="brush:jscript">/定义
function car(color,doors) {
    this.color = color;
    this.doors = doors;
    if (typeof car._initialized == &quot;undefined&quot;) {
        car.prototype.showColor = function() {
            alert(this.color);
        };
    }
    car._initialized = true;
}
//调用
aCar = new car(&#39;red&#39;,4);
aCar.showColor();
</pre>
<p><strong>总结：</strong></p>
<p>这些是JavaScript类定义的几种基本模式，实际每种模式下定义出的属性和类都是有区别的，经典模式和工厂模式因为不符合OOP的语法习惯，基本没有人用了。我们通常使用构造模式和原型模式的混合定义类</p>
<p><strong>目前最流行的也是最实用的类定义结构如下：<br />
	</strong></p>
<pre class="brush:jscript">//用构造模式定义类的构造器和属性
function car(color,doors){
	//用构造模式定义属性
	this.color = color;
	this.doors = doors;
}

//用原型模式定义方法
car.prototype.showColor = function(){
	alert(this.color);
};

//这是静态属性
car.type = &#39;vehicle&#39;;

aCar = new car(&#39;red&#39;,4);
aCar.showColor();
</pre>
<p>1.使用构造模式定义类的构造函数和非函数属性</p>
<p>2.使用原型模式定义类的函数属性（方法）</p>
<p>3.可以通过ClassName.name的方式定义静态属性</p>
<p>4.函数（方法）在本质上也是一种属性，有关各种属性定义方式的区别可以参看后面的参考章节。</p>
<p>参看章节：</p>
<blockquote>
<p>http://blog.csdn.net/avon520/archive/2009/01/17/3819751.aspx</p>
<p><a class="title" href="http://lee.kometo.com/archives/469" rel="bookmark">Javascript类- 几种属性的定义方式及区别</a></p>
<p><a class="title" href="http://lee.kometo.com/archives/471" rel="bookmark">Javascript类-构造方法和原型方法的区别</a></p>
</blockquote>
<p><span style="color: rgb(255, 0, 0);">&nbsp;<br />
	</span></p>
]]></content:encoded>
			<wfw:commentRss>http://lee.kometo.com/archives/439/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Javascript类-构造方法和原型方法的区别</title>
		<link>http://lee.kometo.com/archives/471</link>
		<comments>http://lee.kometo.com/archives/471#comments</comments>
		<pubDate>Sat, 12 Dec 2009 11:23:20 +0000</pubDate>
		<dc:creator>kometo</dc:creator>
				<category><![CDATA[WEB应用开发]]></category>
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://lee.kometo.com/?p=471</guid>
		<description><![CDATA[对Javascript来说，方法在本质上也是一种属性。 构 造方法 和构造属性一样，它是分别存储于每个实例之中的，相互之间是完全独立。 原型方法 和原型属性一样，他是存储于原型中的，每个实例中存储的实际上一 个指向原型的指针。 所有对原型方法的修改会影响到所有实例，而构造方法实际上只能通过实例来访问和修改，也只会影响到相应的实例。 先写结论：方法通常应该使用原型模式定义，并且在必要时通过原型来动态重定义，避免使用构造模式定义方法。 看看示例代码吧： 我们首先构造一个简单的类car,定义2个方法，分别是构造方式定义的constructFunction 和 原型方式定义的 prototypeFunction function echo(str){document.write(&#39;&#60;div&#62;&#39;+str+&#39;&#60;div&#62;&#39;);} function car(){ this.constructFunction = function(){ echo(&#39;This is constructFunction&#39;); }; } car.prototype.prototypeFunction = function(){ echo(&#39;This is prototypeFunction&#39;); }; aCar = new car(); bCar = new car(); aCar.constructFunction(); aCar.prototypeFunction(); bCar.constructFunction(); bCar.prototypeFunction(); 输出结果： This is constructFunction This is prototypeFunction This is constructFunction [...]]]></description>
			<content:encoded><![CDATA[<p><strong>对Javascript来说，方法在本质上也是一种属性。</strong></p>
<p><strong>构 造方法</strong> 和构造属性一样，它是分别存储于每个实例之中的，相互之间是完全独立。</p>
<p><strong>原型方法</strong> 和原型属性一样，他是存储于原型中的，每个实例中存储的实际上一 个指向原型的指针。</p>
<p>所有对原型方法的修改会影响到所有实例，而构造方法实际上只能通过实例来访问和修改，也只会影响到相应的实例。</p>
<p><strong>先写结论：方法通常应该使用原型模式定义，并且在必要时通过原型来动态重定义，避免使用构造模式定义方法。</strong></p>
<p><span id="more-471"></span></p>
<p><strong>看看示例代码吧：</strong> <strong> </strong> 我们首先构造一个简单的类car,定义2个方法，分别是构造方式定义的constructFunction 和 原型方式定义的 prototypeFunction</p>
<pre class="brush:jscript">function echo(str){document.write(&#39;&lt;div&gt;&#39;+str+&#39;&lt;div&gt;&#39;);}

function car(){
   this.constructFunction = function(){
       echo(&#39;This is constructFunction&#39;);
   };
}

car.prototype.prototypeFunction = function(){
    echo(&#39;This is prototypeFunction&#39;);
};

aCar = new car();
bCar = new car();

aCar.constructFunction();
aCar.prototypeFunction();
bCar.constructFunction();
bCar.prototypeFunction();
</pre>
<p>输出结果：</p>
<blockquote>
<div>This is constructFunction</div>
<div>This is prototypeFunction</div>
<div>This is constructFunction</div>
<div>This is prototypeFunction</div>
</blockquote>
<p><strong>原型方法可以随时动态定义和修改</strong>，修改的方法当然是通过类的原型访问，通过重新定义原型方法可以影响到类的所有实例：</p>
<pre class="brush:jscript" lang="javascript">aCar = new car();
bCar = new car();

car.prototype.prototypeFunction = function(){
	echo(&#39;This a new prototypeFunction&#39;);
};

aCar.prototypeFunction();
bCar.prototypeFunction();</pre>
<div><span style="font-size: small;">输出结果为：</span></div>
<div>
<blockquote>
<div><span style="font-size: small;">This a new prototypeFunction</span></div>
<div><span style="font-size: small;">This a new prototypeFunction</span></div>
</blockquote>
</div>
<p>可以看到，即使在实例已经创建以后，对原型的修改也可以反映到影响到所有实例上来。</p>
<p><strong>构造方法是无法通过原型来访问的，只能通过实例访问，也只能通过实例来重定义。下面代码尝试修改实例：aCar的方法constructFunction</strong></p>
<pre class="brush:jscript" lang="javascript">aCar = new car();
bCar = new car();
cCar = new car();

// car.constructFunction() 尝试通过类或者类的原型访问构造定义的方法是无效的，会报错
// car.prototype..constructFunction() 尝试通过类或者类的原型访问构造定义的方法是无效的，会报错

aCar.constructFunction = function(){
    echo(&#39;This a new constructFunction&#39;);
}

aCar.constructFunction();
bCar.constructFunction();
cCar.constructFunction();</pre>
<p>输出结果：</p>
<blockquote>
<div>
<div>
<div>This a new constructFunction</div>
<div>This is constructFunction</div>
<div>This is constructFunction</div>
</p></div>
</p></div>
</blockquote>
<p>对实例aCar的构造方法和影响到了aCar而没有影响到其它实例</p>
<p><strong>事实上，原型方法也是可以通过实例直接修改的，如果直接修改实例的原型方法会出现什么情况呢？</strong></p>
<p><strong><span style="font-weight: normal;">本 段开头已经指出：&ldquo;每个实例中原形方法存储的实际上一个指向原型的指针&rdquo;，如果你尝试修改实例的原型方法，就改变这个指针，使其指向新定义的方法函数；而 原型中的方法定义并没有受到影响。同时，指针既然转向，那么该实例的这个原型方法也就脱离了原型的定义，而成为一个独立方法。</span></strong> <strong><span style="font-weight: normal;">通过下面的代码可以清晰的明白这种过程：</span></strong></p>
<pre class="brush:jscript" lang="javascript">aCar = new car();
bCar = new car();
cCar = new car();

//修改aCar的原型方法 prototypeFunction
aCar.prototypeFunction = function(){
    echo(&#39;This a new prototypeFunction&#39;);
}
//检查修改结果
aCar.prototypeFunction();
bCar.prototypeFunction();
cCar.prototypeFunction();

//修改原型方法 prototypeFunction&nbsp;，就会发现奥妙之处了
car.prototype.prototypeFunction = function(){
    echo(&#39;This a new prototypeFunction modified by prototype&#39;);
}
//检查修改结果
aCar.prototypeFunction();
bCar.prototypeFunction();
cCar.prototypeFunction();</pre>
<div>输出结果：</div>
<div>
<blockquote>
<div>
<div>//第一段的输出结果</div>
<div>This a new prototypeFunction &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //在修改aCar的原型方法prototypeFunction时，仅aCar受到了影响</div>
<div>This is prototypeFunction</div>
<div>This is prototypeFunction</div>
<div>//第二段的输出结果</div>
<div>//我们重新定义了car的原型方法prototypeFunction，但是aCar没有受到影响，aCar的方法prototypeFunction已经脱离了原型的影响。</div>
<div>This a new prototypeFunction</div>
<div>This a new prototypeFunction modified by prototype</div>
<div>This a new prototypeFunction modified by prototype</div>
</p></div>
</blockquote>
</div>
<p><span style="color: rgb(255, 0, 0);"><strong>注意:直接修改实例的原型方法虽然是可行的,但是会带来代码上的混淆和混乱,要尽可能避免使用这种方式.</strong></span></p>
]]></content:encoded>
			<wfw:commentRss>http://lee.kometo.com/archives/471/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Javascript类- 几种属性的定义方式及区别</title>
		<link>http://lee.kometo.com/archives/469</link>
		<comments>http://lee.kometo.com/archives/469#comments</comments>
		<pubDate>Sat, 12 Dec 2009 11:20:53 +0000</pubDate>
		<dc:creator>kometo</dc:creator>
				<category><![CDATA[WEB应用开发]]></category>
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://lee.kometo.com/?p=469</guid>
		<description><![CDATA[几种属性： 先看代码，这段代码中出现了类定义中可能使用到5种属性或者变量 function car(param1,param2){ //构造变量 var varProperty = &#39;This is a var Perperty&#39;; //构造属性 this.constructProperty = &#39;This is a construct Property&#39; } //原形属性 car.prototype.prototypeProperty = &#39;This is a prototype property&#39;; //静态属性 car.staticProperty = &#39;This is a static property&#39;; 构造变量 使用VAR声明和定义，它的作用域仅限于构造方法内部，包括在构造器内部定义的所有方法（构造方法）。直接通过变量名访问：varProperty。有些文章也把叫做私有属性，从作用域上看，它是私有的，但它不是属性，类的原型是无法访问它的。 构造参数 就是上述代码中的 param1,param2,它与构造变量有相同的作用域和方法方式 function car(param1,param2){ //构造变量 var varProperty = &#39;This is a var Perperty&#39;; echo(varProperty); [...]]]></description>
			<content:encoded><![CDATA[<h3>几种属性：</h3>
<p>先看代码，这段代码中出现了类定义中可能使用到5种属性或者变量</p>
<pre class="brush:jscript">function car(param1,param2){
    //构造变量
    var varProperty = &#39;This is a var Perperty&#39;;
    //构造属性
    this.constructProperty = &#39;This is a construct Property&#39;
}

//原形属性
car.prototype.prototypeProperty = &#39;This is a prototype property&#39;;

//静态属性
car.staticProperty = &#39;This is a static property&#39;;
</pre>
<h3><span id="more-469"></span></h3>
<p><strong>构造变量</strong> 使用VAR声明和定义，它的作用域仅限于构造方法内部，包括在构造器内部定义的所有方法（构造方法）。直接通过变量名访问：varProperty。有些文章也把叫做私有属性，从作用域上看，它是私有的，但它不是属性，类的原型是无法访问它的。</p>
<p><strong>构造参数</strong> 就是上述代码中的 param1,param2,它与构造变量有相同的作用域和方法方式</p>
<pre class="brush:jscript">function car(param1,param2){
    //构造变量
    var varProperty = &#39;This is a var Perperty&#39;;

    echo(varProperty);
    echo(param1);

    this.someMethod = function(){
        echo(varProperty);
        echo(param1);
     };
}</pre>
<p><strong><br />
	</strong></p>
<p><strong>构造属性</strong> 构造属性在类的构造器中通过this.定义，它是公开的(public)，可以通过类的实例(this.)直接访问和修改它</p>
<p><strong>原型属性</strong> 在类的原型中定义，它也是公开，具有和构造属性相同的作用域，它不仅可以通过实例访问，也可以随时通过原型来访问（(ClassName.propertype.)</p>
<p>它和构造属性是有区别的：<span style="background-color: rgb(255, 255, 0);">原型属性可以通过原型直接访问，它存储于类的原型中的，各个实例是通过指针共享访问它</span><strong>。</strong>具体下面单独分析</p>
<pre class="brush:jscript">function car(){

    //构造属性
    this.constructProperty = &#39;This is a construct Property&#39;

    this.someMethod = function(){
        echo(this.constructProperty); //这样可以
        echo(this.ptototypeProperty); //这一可以
     };
}

//原形属性
car.prototype.prototypeProperty = &#39;This is a prototype property&#39;;

echo(car.constructProperty);  //这样是不能访问构造属性的
echo(car.ptototypeProperty);  //这样是不能访问原型属性的

//必须通过实例来访问
aCar = new car();
echo(aCar.constructProperty);  //这样可以
echo(aCar.ptototypeProperty);  //这样可以

echo(car.prototypeProperty)    //原型属性可以通过原型直接访问
</pre>
<p>&nbsp;</p>
<p><strong>静态属性 </strong>直接通过ClassName.的方式定义，它具有和常规OOP语言中的静态属性类似的特性，但注意，它只能通过ClassName访问，不能通过实例访问，在类的中也不能通过this访问</p>
<pre class="brush:jscript">function car(param1,param2){
    echo(this.staticProperty);//这样是不能访问到静态属性的。
    echo(car.staticProperty);//这样可以访问到静态属性的。
}

//静态属性
car.staticProperty = &#39;This is a static property&#39;;

aCar = new car();
echo(aCar.staticPerperty); //这样是不能访问到静态属性的。
echo(car.staticProperty); //这样可以访问到静态属性的。</pre>
<h3>构造属性和原型属性的区别：</h3>
<p>上面已经说了构造属性和原型属性的定义方式，和访问方法，它们的主要区别在于：<span style="background-color: rgb(255, 255, 0);">原型属性可以通过原型直接访问，它存储于类的原型中的，各个实例是通过指针共享访问它</span><strong>。也就是说对于每个构造属性，每个实例都有一个自己存储副本；而对于每个原形属性，每个实例实际上是共享同一个存储副本，实例中存储的仅仅是一个指向原型属性的指针。</strong></p>
<p><strong>看代码吧：</strong></p>
<pre class="brush:jscript">function car(){
    //构造属性
    this.constructProperty = new Array (&#39;tom&#39;,&#39;jerry&#39;);
}

//原形属性
car.prototype.prototypeProperty = new Array (&#39;tom&#39;,&#39;jerry&#39;);

aCar = new car();
bCar = new car();
cCar = new car();

//修改aCar的构造属性
aCar.constructProperty.push(&#39;Emeric&#39;);
echo(aCar.constructProperty);
echo(bCar.constructProperty);
echo(bCar.constructProperty);

//修改aCar的原型属性
aCar.prototypeProperty.push(&#39;Emeric&#39;);
echo(aCar.prototypeProperty);
echo(bCar.prototypeProperty);
echo(bCar.prototypeProperty);
</pre>
<p>输出结果：</p>
<blockquote>
<div>//改变aCar的构造属性，仅仅影响到的aCar单一实例</div>
<div>tom,jerry,Emeric</div>
<div>tom,jerry</div>
<div>tom,jerry</div>
<div>//改变aCar的原型属性，影响到了所有实例</div>
<div>tom,jerry,Emeric</div>
<div>tom,jerry,Emeric</div>
<div>tom,jerry,Emeric</div>
</blockquote>
<p>这里我们为什么在示例代码中使用数组，而没有使用其它简单变量呢？来看另一段代码：这段代码的和上面的唯一区别是使用了字符串作为属性，</p>
<pre class="brush:jscript">function car(){
    //构造属性
    this.constructProperty = &#39;This is a construct Property&#39;
}

//原形属性
car.prototype.prototypeProperty = &#39;This is a prototype property&#39;;

aCar = new car();
bCar = new car();
cCar = new car();

aCar.constructProperty = &#39;New string&#39;;
echo(aCar.constructProperty);
echo(bCar.constructProperty);
echo(bCar.constructProperty);

aCar.prototypeProperty = &#39;New string&#39;;
echo(aCar.prototypeProperty);
echo(bCar.prototypeProperty);
echo(bCar.prototypeProperty);
</pre>
<p>输出结果如下，对aCar的两种属性的修改都没有影响到其它实例，正如上面所说，javascript在实例中使用指针来指向原型属性，当使用<span style="color: rgb(0, 100, 0);"> <strong>aCar.prototypeProperty = &#39;New string&#39;</strong> </span>进行直接赋值时，javascript进行的操作是修改实例的指针（<span style="color: rgb(0, 100, 0);"><strong>aCar.prototypeProperty ）</strong></span>，使其指向新的存储副本<span style="color: rgb(0, 100, 0);"><strong> &#39;New string&#39;</strong> </span>，这一过程往往会掩盖了原型属性的共享特性。</p>
<p>&nbsp;</p>
<blockquote>
<div>New string</div>
<div>This is a construct Property</div>
<div>This is a construct Property</div>
<div>New string</div>
<div>This is a prototype property</div>
<div>This is a prototype property</div>
</blockquote>
<p>再看一段补充代码，这是接着上面的代码运行的，我们通过原型来直接修改了原型属性：</p>
<pre class="brush:jscript">car.prototype.prototypeProperty = &#39;Another New String!&#39;;
echo(aCar.prototypeProperty);
echo(bCar.prototypeProperty);
echo(bCar.prototypeProperty);
</pre>
<p>输出结果如下，会发现，这一修改仅仅影响到了bCar和cCar。</p>
<p>原因其实就是因为上面<span style="color: rgb(0, 100, 0);"> <strong>aCar.prototypeProperty = &#39;New string&#39;</strong> </span> 的，它改变了<span style="color: rgb(0, 100, 0);"> <strong>aCar.prototypeProperty </strong></span>的指向，而不再指向 原型，因而他也就脱离了原型的控制。</p>
<blockquote>
<div>New string</div>
<div>Another New String!</div>
<div>Another New String!</div>
</blockquote>
<p>由于原型属性的共享特性和可能发生的实例指针脱离原型的现象，<strong><span style="color: rgb(255, 0, 0);">我们应该仅仅对需要共享的属性使用原型定义，一般的属性应该尽量使用构造来定义；</span></strong><strong><span style="color: rgb(255, 0, 0);">在修改原型属性时应该尽可能通过原型(car.prototype.)来访问修改，而不要通过实例(aCar.)来修改；。</span></strong>以此来避免可能发生的属性混乱问题。</p>
]]></content:encoded>
			<wfw:commentRss>http://lee.kometo.com/archives/469/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Debian+ISPCP 环境下 eAccelerator效果测试</title>
		<link>http://lee.kometo.com/archives/397</link>
		<comments>http://lee.kometo.com/archives/397#comments</comments>
		<pubDate>Fri, 30 Oct 2009 11:39:36 +0000</pubDate>
		<dc:creator>kometo</dc:creator>
				<category><![CDATA[WEB应用开发]]></category>

		<guid isPermaLink="false">http://lee.kometo.com/?p=397</guid>
		<description><![CDATA[硬件：CPU 2.5 / 1G内存 / VMEsxi虚拟环境 :roll: 软件：Debian Lenny 5.0 + ISPCP 1.0.2 stable 工具：apache 里的AB 声名：这是在一个非标准环境下的测试，测试结果不具有普遍可比性，仅供参考 eAccelerator的对比测试结果 测试应用网站：3个 A 一个简单的模拟PHPINFO类页面，提取系统信息，显示，单文件程序 B 一个自己开发的CMS系统 C WordPress BLOG，加载了一些常见插件 测试方式：使用 ab -t 60 -c 5 参数测试，每阶段2次测试取评价值，分2个阶段 P1 没有安装eAcceleratr P2  安装了eAccelerator AB 测试结果表 （请求处理/秒）        P1 P2   Req/S CPU%  Req/S  CPU% A INFO   73 40   75  20 B CMS   8.72  100  16.77  95 C [...]]]></description>
			<content:encoded><![CDATA[<p><strong>硬件：</strong>CPU 2.5 / 1G内存 / VMEsxi虚拟环境 :roll:</p>
<p><strong>软件：</strong>Debian Lenny 5.0 + ISPCP 1.0.2 stable</p>
<p><strong>工具：</strong>apache 里的AB</p>
<p style="TEXT-ALIGN: center"><strong>声名：这是在一个非标准环境下的测试，测试结果不具有普遍可比性，仅供参考</strong></p>
<h2>eAccelerator的对比测试结果</h2>
<p><strong>测试应用网站：</strong>3个</p>
<ul>
<li>A 一个简单的模拟PHPINFO类页面，提取系统信息，显示，单文件程序</li>
<li>B 一个自己开发的CMS系统</li>
<li>C WordPress BLOG，加载了一些常见插件</li>
</ul>
<p><strong>测试方式：</strong>使用 <strong>ab -t 60 -c 5</strong> 参数测试，每阶段2次测试取评价值，分2个阶段</p>
<ul>
<li>P1 没有安装eAcceleratr</li>
<li>P2  安装了eAccelerator</li>
</ul>
<table style="width: 500px;" border="1" cellpadding="3" align="center">
<caption>AB 测试结果表 （请求处理/秒）</caption>
<tbody>
<tr>
<td rowspan="2">  <span style="color: #ff0000;"><strong> </strong></span> </td>
<td style="TEXT-ALIGN: center" colspan="2">  <strong><span style="color: #ff0000;">P1</span></strong></td>
<td style="TEXT-ALIGN: center" colspan="2"><strong><span style="color: #ff0000;">P2</span></strong>  </td>
</tr>
<tr>
<td style="TEXT-ALIGN: center"><span style="color: #ff0000;"><strong><span style="color: #ff0000;">Req/S</span></strong></span></td>
<td style="TEXT-ALIGN: center"><span style="color: #ff0000;"><strong><span style="color: #ff0000;">CPU%</span></strong></span></td>
<td style="TEXT-ALIGN: center"><span style="color: #ff0000;"><strong><span style="color: #ff0000;"> Req/S</span></strong></span></td>
<td style="TEXT-ALIGN: center"><strong><span style="color: #ff0000;"> CPU%</span></strong></td>
</tr>
<tr>
<td><span style="color: #339966;">A INFO</span> </td>
<td> 73</td>
<td>40 </td>
<td> 75</td>
<td> 20</td>
</tr>
<tr>
<td><span style="color: #339966;">B CMS</span> </td>
<td> 8.72</td>
<td> 100</td>
<td> 16.77</td>
<td> 95</td>
</tr>
<tr>
<td><span style="color: #339966;">C WordPress</span></td>
<td> 1.22</td>
<td> 100</td>
<td> 1.76</td>
<td>100 </td>
</tr>
</tbody>
</table>
<p><strong>分析：</strong></p>
<p><span id="more-397"></span></p>
<p><strong>依照CMS应用为典型WEB应用需要环境，可以看到eAccelerator提高效率高达100%，综合环境变化情况，至少我们可以期望有50%的提高，从A和B成绩对比来看，过于简单的脚本和过于复杂的脚本环境下，eAccelerator表现就不是很突出，当然，这也木桶原理的表现。</strong></p>
<p><strong>从A/B的对比成绩，我们还可以看出，eAccelerator因为可以缓存脚本编译结果，由此带来的CPU占用率的降低是很明显的。</strong></p>
<h2>eAccelerator环境下的压力测试：</h2>
<p><strong>测试应用网站：</strong></p>
<ul>
<li>A 一个简单的模拟PHPINFO类页面，提取系统信息，显示，单文件程序</li>
<li>B 一个自己开发的CMS系统</li>
<li>C WordPress BLOG，加载了一些常见插件</li>
<li>D 一个最简单的静态HTML文件，仅显示几个字符，主要测试APACHE的静态响应能力</li>
</ul>
<p><strong>测试方法：</strong>使用 ab -t 30 -c X 参数测试，每阶段2次测试取平均值</p>
<p>X分别取 1 / 2 /5 /15 /60 分段测试，根据具体应用，某些分段没有测试意义，跳过了</p>
<p><strong>A </strong><strong>INFO 页面压力分段测试成绩</strong></p>
<table style="width: 500px; cursor: default;" border="1" cellpadding="3" align="center">
<tbody>
<tr>
<td style="color: #000000; font-size: 11px; cursor: text; text-align: right; margin: 8px;"><span style="color: #ff0000;"><strong>并发线程数</strong></span></td>
<td style="color: #000000; font-size: 11px; cursor: text; margin: 8px;"><span style="color: #ff0000;"><strong>请求处理/秒</strong></span></td>
<td>平均页面读取时间</td>
<td>CPU</td>
</tr>
<tr>
<td style="color: #000000; font-size: 11px; cursor: text; margin: 8px;"><span style="color: #339966;">5</span></td>
<td style="color: #000000; font-size: 11px; cursor: text; margin: 8px;">75</td>
<td>65</td>
<td> </td>
</tr>
<tr>
<td>10</td>
<td>85</td>
<td>116</td>
<td>20</td>
</tr>
<tr>
<td>15</td>
<td>83.92</td>
<td>178</td>
<td> </td>
</tr>
<tr>
<td>20</td>
<td>81.11</td>
<td>546</td>
<td> </td>
</tr>
<tr>
<td>50</td>
<td>72</td>
<td>692</td>
<td> </td>
</tr>
<tr>
<td>60</td>
<td>84.23</td>
<td>712</td>
<td>50</td>
</tr>
</tbody>
</table>
<p><strong>B CMS页面压力分段测试成绩</strong></p>
<table style="width: 500px; cursor: default;" border="1" cellpadding="3" align="center">
<tbody>
<tr>
<td style="color: #000000; font-size: 11px; cursor: text; text-align: right; margin: 8px;"><span style="color: #ff0000;"><strong>并发线程数</strong></span></td>
<td style="color: #000000; font-size: 11px; cursor: text; margin: 8px;"><span style="color: #ff0000;"><strong>请求处理/秒</strong></span></td>
<td style="color: #000000; font-size: 11px; cursor: text; margin: 8px;">平均页面读取时间</td>
<td style="color: #000000; font-size: 11px; cursor: text; margin: 8px;">CPU</td>
</tr>
<tr>
<td>1</td>
<td>13.84</td>
<td>72</td>
<td>75</td>
</tr>
<tr>
<td>2</td>
<td>14.4</td>
<td>138</td>
<td>91</td>
</tr>
<tr>
<td style="color: #000000; font-size: 11px; cursor: text; margin: 8px;"><span style="color: #339966;">5</span></td>
<td style="color: #000000; font-size: 11px; cursor: text; margin: 8px;">16.77</td>
<td style="color: #000000; font-size: 11px; cursor: text; margin: 8px;">298</td>
<td style="color: #000000; font-size: 11px; cursor: text; margin: 8px;">95</td>
</tr>
<tr>
<td style="color: #000000; font-size: 11px; cursor: text; margin: 8px;">10</td>
<td style="color: #000000; font-size: 11px; cursor: text; margin: 8px;">16.22</td>
<td style="color: #000000; font-size: 11px; cursor: text; margin: 8px;">-</td>
<td style="color: #000000; font-size: 11px; cursor: text; margin: 8px;">98</td>
</tr>
<tr>
<td style="color: #000000; font-size: 11px; cursor: text; margin: 8px;">60</td>
<td style="color: #000000; font-size: 11px; cursor: text; margin: 8px;">11.89</td>
<td style="color: #000000; font-size: 11px; cursor: text; margin: 8px;">5045</td>
<td style="color: #000000; font-size: 11px; cursor: text; margin: 8px;">100</td>
</tr>
</tbody>
</table>
<p><strong>C WordPress页面压力分段测试成绩</strong></p>
<table style="width: 500px; cursor: default;" border="1" cellpadding="3" align="center">
<tbody>
<tr>
<td style="color: #000000; font-size: 11px; cursor: text; text-align: right; margin: 8px;"><span style="color: #ff0000;"><strong>并发线程数</strong></span></td>
<td style="color: #000000; font-size: 11px; cursor: text; margin: 8px;"><span style="color: #ff0000;"><strong>请求处理/秒</strong></span></td>
<td style="color: #000000; font-size: 11px; cursor: text; margin: 8px;">平均页面读取时间</td>
<td style="color: #000000; font-size: 11px; cursor: text; margin: 8px;">CPU</td>
</tr>
<tr>
<td>1</td>
<td>1.93</td>
<td>517</td>
<td>97</td>
</tr>
<tr>
<td style="color: #000000; font-size: 11px; cursor: text; margin: 8px;"><span style="color: #339966;">5</span></td>
<td style="color: #000000; font-size: 11px; cursor: text; margin: 8px;">1.76</td>
<td style="color: #000000; font-size: 11px; cursor: text; margin: 8px;">2848</td>
<td style="color: #000000; font-size: 11px; cursor: text; margin: 8px;">100</td>
</tr>
<tr>
<td style="color: #000000; font-size: 11px; cursor: text; margin: 8px;">10</td>
<td style="color: #000000; font-size: 11px; cursor: text; margin: 8px;">1.82</td>
<td style="color: #000000; font-size: 11px; cursor: text; margin: 8px;">5505</td>
<td style="color: #000000; font-size: 11px; cursor: text; margin: 8px;">100</td>
</tr>
<tr>
<td style="color: #000000; font-size: 11px; cursor: text; margin: 8px;">60</td>
<td style="color: #000000; font-size: 11px; cursor: text; margin: 8px;">1.81</td>
<td style="color: #000000; font-size: 11px; cursor: text; margin: 8px;">5520</td>
<td style="color: #000000; font-size: 11px; cursor: text; margin: 8px;">100</td>
</tr>
</tbody>
</table>
<p><strong>D 简单静态HTML页面</strong></p>
<table style="width: 500px; cursor: default;" border="1" cellpadding="3" align="center">
<tbody>
<tr>
<td style="color: #000000; font-size: 11px; cursor: text; text-align: right; margin: 8px;"><span style="color: #ff0000;"><strong>并发线程数</strong></span></td>
<td style="color: #000000; font-size: 11px; cursor: text; margin: 8px;"><span style="color: #ff0000;"><strong>请求处理/秒</strong></span></td>
<td>平均页面读取时间</td>
<td>CPU</td>
</tr>
<tr>
<td>1</td>
<td>524</td>
<td>1.5</td>
<td>20</td>
</tr>
<tr>
<td style="color: #000000; font-size: 11px; cursor: text; margin: 8px;">5</td>
<td style="color: #000000; font-size: 11px; cursor: text; margin: 8px;">689</td>
<td>7</td>
<td> 35</td>
</tr>
<tr>
<td>10</td>
<td>694</td>
<td>14</td>
<td>38</td>
</tr>
<tr>
<td>50</td>
<td>713</td>
<td>70</td>
<td>43 </td>
</tr>
</tbody>
</table>
<p><strong>分析：</strong></p>
<ol>
<li>此测试环境典型WEB应用的最佳并发连接支持大约在每秒十个左右（低不低？）</li>
<li>WordPress确实是个巨无霸</li>
<li>针对A的测试结果，我们可以认为，系统响应瓶颈应该在IO部分</li>
<li>针对 B / C 的测试结果，我们可以认为系统响应的瓶颈在CPU</li>
<li>本来想进一步提高静态页面测试压力的，可是ab在我的Windows Server环境下总是有问题<br />
先是报这个错，后来换个AB版本解决了<br />
apr_pollset_create failed: Invalid argument (22)       <br />
又开始报这个错。。。郁闷<br />
apr_socket_recv: 您的主机中的软件放弃了一个已建立的连接。   (730053)</li>
</ol>
<p> BTW：我一开始的测试结果很低，后来发现问题出在我的测试客户端需要通过一条RouterOS路由器访问服务器，而且还要NAT转换一下，严重影响了测试结果，我把当时使用RouterOS路由时的测试结果也贴上来吧，仅供娱乐：</p>
<table style="width: 500px;" border="1" cellpadding="3" align="center">
<caption> 娱乐测试结果表 （请求处理/秒）</caption>
<tbody>
<tr>
<td style="text-align: right;"><span style="color: #ff0000;"><strong>请求处理/秒</strong></span></td>
<td><span style="color: #ff0000;"><strong>P1</strong></span></td>
<td><span style="color: #ff0000;"><strong>P2</strong></span></td>
</tr>
<tr>
<td><span style="color: #339966;">A INFO</span></td>
<td>10.22</td>
<td>10.39</td>
</tr>
<tr>
<td><span style="color: #339966;">B WordPress</span></td>
<td>1.35</td>
<td>1.57</td>
</tr>
<tr>
<td><span style="color: #339966;">C CMS</span></td>
<td>3.10</td>
<td>3.43</td>
</tr>
</tbody>
</table>
]]></content:encoded>
			<wfw:commentRss>http://lee.kometo.com/archives/397/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>从Etach到Lenny，Debian+ISPCP升级笔记</title>
		<link>http://lee.kometo.com/archives/385</link>
		<comments>http://lee.kometo.com/archives/385#comments</comments>
		<pubDate>Fri, 30 Oct 2009 04:00:42 +0000</pubDate>
		<dc:creator>kometo</dc:creator>
				<category><![CDATA[IT前沿]]></category>
		<category><![CDATA[WEB应用开发]]></category>
		<category><![CDATA[Debian]]></category>
		<category><![CDATA[ispcp]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[log]]></category>
		<category><![CDATA[server]]></category>

		<guid isPermaLink="false">http://lee.kometo.com/?p=385</guid>
		<description><![CDATA[本来有一台Linux服务器，运行Debian 4.0 Etach 和 ISPCP 1.0.0 RC6 近期看到ISPCP正式版已经发布好久了,就决定升级.升级路线是首先 升级Debian 到 Lenny (5.0),然后再升级ISPCP A 升级Linux 升级的方法很简单 1) (可选的) 检查你的更新源列表（sources.list) apt-spy -d stable -t 5 update #是用Stable或者Lenny现阶段效果应该是一样的 有些指南让你加上国家和地区参数，时间没有必要，事实上我们访问最快的源往往都在国外。 你也可以手动去更新 /etc/apt/sources.list 2) 更新系统 aptitude update &#38;&#38; aptitude upgrade 这一步可能需要反复运行几次，如果有软件版本冲突提示，你需要运行 aptitude 手动选择冲突解决方案 一直运行到aptitude update &#38;&#38; aptitude upgrade提示没有需要更新软件包了，系统升级完成 3)可能遇到的问题 我遇到问题是：Mysql升级到5.2以后不能自动启动了，检查 /etc/log/daemon.log发现一个提示 /etc/init.d/mysql[2130]: ERROR: Using expire_logs_days without log_bin crashes the server. [...]]]></description>
			<content:encoded><![CDATA[<p>本来有一台Linux服务器，运行Debian 4.0 Etach 和 ISPCP 1.0.0 RC6</p>
<p>近期看到ISPCP正式版已经发布好久了,就决定升级.升级路线是首先 升级Debian 到 Lenny (5.0),然后再升级ISPCP</p>
<h2>A 升级Linux</h2>
<p>升级的方法很简单</p>
<p><strong>1) (可选的) 检查你的更新源列表（sources.list)</strong></p>
<p>apt-spy -d stable -t 5 update #是用Stable或者Lenny现阶段效果应该是一样的</p>
<p>有些指南让你加上国家和地区参数，时间没有必要，事实上我们访问最快的源往往都在国外。</p>
<p>你也可以手动去更新 /etc/apt/sources.list</p>
<p><strong>2) 更新系统</strong></p>
<p>aptitude update &amp;&amp; aptitude upgrade</p>
<p>这一步可能需要反复运行几次，如果有软件版本冲突提示，你需要运行 aptitude 手动选择冲突解决方案</p>
<p>一直运行到aptitude update &amp;&amp; aptitude upgrade提示没有需要更新软件包了，系统升级完成</p>
<p><strong>3)可能遇到的问题</strong></p>
<p>我遇到问题是：Mysql升级到5.2以后不能自动启动了，检查 /etc/log/daemon.log发现一个提示</p>
<blockquote><p>/etc/init.d/mysql[2130]: ERROR: Using expire_logs_days without log_bin crashes the server. See README.Debian.gz</p>
</blockquote>
<div id="_mcePaste" style="position: absolute; overflow-x: hidden; overflow-y: hidden; width: 1px; height: 1px; top: 0px; left: -10000px;">log_bin = /var/log/mysql/mysql-bin.log</div>
<div id="_mcePaste" style="position: absolute; overflow-x: hidden; overflow-y: hidden; width: 1px; height: 1px; top: 0px; left: -10000px;">expire_logs_days = 10</div>
<p>修改 /etc/mysql/my.cnf 解决问题</p>
<blockquote><p>#log_bin = /var/log/mysql/mysql-bin.log #这一行本来是被注释掉的</p>
<p>expire_logs_days = 10</p>
</blockquote>
<p>完成上述步骤后服务器及ISPCP应该仍然可以正常工作，检查处理完可能存在的问题后，准备升级ISPCP</p>
<h2>B) 更新 ISPCP到 1.0.2</h2>
<p>安装ISCP官方说明逐步操作</p>
<p><a href="http://www.isp-control.net/documentation/doku.php?id=start:upgrade:rc" target="_blank">http://www.isp-control.net/documentation/doku.php?id=start:upgrade:rc</a></p>
<p>几点说明：</p>
<p><span id="more-385"></span></p>
<p><strong>1）更新/ect/apt/sourcs.list</strong></p>
<p>直接使用上述apt-spy获取的sources.list,按如下格式添加 contrib 和 non-free 参数</p>
<blockquote><p>deb http://ftp.tw.debian.org/debian/ lenny main <strong>contrib non-free</strong></p>
<p>deb http://security.debian.org/ lenny/updates main <strong>contrib non-free</strong></p>
<p>deb-src http://ftp.tw.debian.org/debian/ lenny main <strong>contrib non-free</strong></p>
</blockquote>
<p><strong>2)</strong> 如果你已经采取了其他系统备份措施，官方说明中的第6步（BACKUPS）是可以跳过的</p>
<p><strong>3)</strong> 第9步：【 cp -Rv /tmp/ispcp/var/* /var/ 】，你可能会遇到一个无法覆盖的提示： /var/www/ispcp/daemon/ispcp_daemon Text in busy，你可以忽略，或者先停止ispcp_daemon【/etc/init.d/ispcp_daemon stop】</p>
<p><strong>4）</strong>如果你在perl ispcp-update 过程中遇到需要输入密码的步骤，如果恰好你又选择了 【auto generated 】，恩，慢慢等吧，不是死机了，就是慢。</p>
<p><strong>5）</strong>如果你安装官方步骤升级完遇到服务器报”500 Server Error”错误</p>
<p>出现这个错误的可能原因很多，首先你需要检查你的Apache，FastCGI，PHP是否使用了非官方集成的插件，比如eAccelerator等。500错误一般出现在FastCGI和PHP引擎。</p>
<p>我的情况是eAccelerator版本过期，因为PHP升级了，所以需要重新编译eAccelerator</p>
<p>有关eAccelerator的安装和配置参阅 <a href="http://isp-control.net/documentation/doku.php?id=howto:eaccelerator" target="_blank">http://isp-control.net/documentation/doku.php?id=howto:eaccelerator</a></p>
<p><strong>6）</strong>学会追踪分析各类日志文件是解决各类问题的最好方法，比如上述500问题，如果不是通过日志分析，想找到问题根源实在是太难。而且ISPCP默认没有启用PHP的错误日志文件记录，我还是手动修改PHP.ini，启用PHP日志后才追踪发现问题的根源的。</p>
<p>/var/log/* 大部分系统LOG文件都是放在这里的</p>
<p><strong>7) </strong>ISPCP的配置和日志文件结构</p>
<pre>/etc
     /apach2
             /apache2.conf           #apache 主配置文件
             /conf.d/*               #附加配置文件
             /mods-*/*               #附加MOD配置文件
             /sites-*/*              #站点配置文件
             /ispcp                  #ISPCP各客户站点配置，这个目录实际上链接到了 /sites-*/* 目录下了
     /php5
             /cgi/php.ini            #php 主配置文件
             /cli/phpini             #php 的 cli 配置文件
             /conf.d/*               #PHP 附加配置文件
     /ispcp
             /ispcp.conf             #ispcp 主配置文件
             /apache/*               #apache 相关的配置文件模板
             /fcgi/*                 #php    相关的配置文件模板和脚本模板
             /*other                 #应该是其他一些相关配置的模板
/var/www
     /fcgi                           #各客户站点的PHP配置文件及FastCGI的PHP启动脚本
             /domain.com             #一个站点
                /php5/php.ini        #PHP 的站点配置文件
                /php5-fcgi-starter   #启动PHP 的FASTCGI脚本
     /ispcp                          #ispcp的运行文件
             /gui                    #管理站点文件
     /virtual/domain.com             #各个客户站点主目录
             /htdocs                 #网站根目录
             /errors                 #错误提示的相关文件HTML
             /cgi-bin                #脚本目录
             /backups                #备份文件，自动/手动
             /logs                   #这个不用说了吧，默认的这里放的是Apache的LOG文件
             /phptmp                 #脚本临时文件，默认的Session文件放这里的
/var/log
     /kern.log                       #系统核心
     /daemon.log                     #系统服务
     /mysql.err
     /mysql.log
     /mysql/*                        #Mysql想关的LOG
     /apache2/*                      #Apache的LOG（Combined,error,traf,suexec等到）还有各个站点，
                                     #这里的LOG和/var/www/virtual//domain.com/log 是什么关系我还没搞清楚
</pre>
<p>8) 关于修改ISPCP配置模板文件以后如何刷新各站点，请参阅：</p>
<p><a href="http://www.isp-control.net/documentation/doku.php?id=howto:ispcp:regenerate_config" target="_blank">http://www.isp-control.net/documentation/doku.php?id=howto:ispcp:regenerate_config</a></p>
<p>关于PHP的站点配置文件刷新，官方说明有误刷新前你必须删除原有的站点配置文件，才会刷新，另外master站点不会刷新的。</p>
<p>ISPCP的各处PHP配置文件加载顺序为<br />
1 /etc/php5/cgi/php.ini<br />
2 /var/www/fcgi/domain.com/php5/php.ini<br />
3 /etc/php5/conf.d/*</p>
<p>下面的配置会覆盖上面的配置，所以你可以把共性的配置定义放到conf.d目录下，专门建立一个文件放置。而把需要每个站点单独配置的特别是设计路径的配置项放到parts/php.ini中，然后刷新生效。</p>
<p>下面是我的对配置文件的修改</p>
<pre lang="ini">;添加到 /etc/ispcp/fcgi/parts/php5/php.ini 结尾
[Append per site]
eaccelerator.cache_dir = "{WWW_DIR}/{DMN_NAME}/phptmp"
error_log               = {WWW_DIR}/{DMN_NAME}/logs/php-error.log
</pre>
<pre lang="ini">;添加到 /etc/php5/conf.d/my.ini

disable_functions = show_source, system, shell_exec, passthru, exec, phpinfo, shell, symlink, popen, proc_open

file_uploads		= On

upload_max_filesize	= 20M
post_max_size		= 30M

;memory_limit		= 128M

max_input_time		= 300
;max_execution_time	= 30 

error_reporting      =  E_ALL &amp; ~E_NOTICE | E_WARNING | E_STRTCT
log_errors             = On
display_errors	= Off
</pre>
<p>下面是我写的一个自动刷新ISPCP PHP配置文件的脚本</p>
<pre lang="sh">#!/bin/sh
/etc/init.d/ispcp_daemon stop

echo 'Enter the password of root for mysql'
mysql -u root -p &lt; ispcp-reset-site-status.sql

echo 'Wating........'
rm -r ispcp-conf-backups
mkdir -p ispcp-conf-backups
mv /var/www/fcgi/*.* ispcp-conf-backups

/var/www/ispcp/engine/ispcp-rqst-mngr
/etc/init.d/ispcp_daemon start

/etc/init.d/apache2 restart
</pre>
<p>配套的SQL文件，务必保存成文件名：ispcp-reset-site-status.sql，并放到和上面脚本相同的目录下</p>
<pre lang="sql">USE ispcp;
UPDATE `domain` SET `domain_status` = 'change' WHERE `domain_status` = 'ok';
UPDATE `subdomain` SET `subdomain_status` = 'change' WHERE `subdomain_status` = 'ok';
UPDATE `domain_aliasses` SET `alias_status` = 'change' WHERE `alias_status` = 'ok';
</pre>
]]></content:encoded>
			<wfw:commentRss>http://lee.kometo.com/archives/385/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>WordPress乱码问题完美解决方案</title>
		<link>http://lee.kometo.com/archives/313</link>
		<comments>http://lee.kometo.com/archives/313#comments</comments>
		<pubDate>Fri, 16 Oct 2009 03:18:22 +0000</pubDate>
		<dc:creator>kometo</dc:creator>
				<category><![CDATA[WEB应用开发]]></category>

		<guid isPermaLink="false">http://lee.kometo.com/?p=313</guid>
		<description><![CDATA[迁移了我的WordPress到一台新的服务器，并升级到最新版本，遇到的乱码问题，搜索了一下，解决方法有几种，修改 wp-inludes/wp-db.php,转换数据库编码等等，但都不完美，先提供完美解决方案如下： 1.指定新目标数据库的编码为 utf8_unicode_ci ,需要你的Mysql版本为4.1+，通过 数据库-&#62;操作 来操作 2.导入数据备份文件 3.修改wp-config.php 文件，增加一行： define(&#8216;DB_CHARSET&#8217;,'utf8&#8242;); OK，完成！ 顺便提一下，低版本数据库导入高版本数据库时，先根据源数据编码指定好新的目标数据库默认编码（通过 数据库-&#62;操作 来操作），可以解决大部分数据升级到乱码问题。]]></description>
			<content:encoded><![CDATA[<p>迁移了我的WordPress到一台新的服务器，并升级到最新版本，遇到的乱码问题，搜索了一下，解决方法有几种，修改 wp-inludes/wp-db.php,转换数据库编码等等，但都不完美，先提供完美解决方案如下：</p>
<p>1.指定新目标数据库的编码为<dfn title="Unicode (多语言), 不区分大小写"> <strong>utf8_unicode_ci</strong></dfn> ,需要你的Mysql版本为4.1+，通过 <strong>数据库-&gt;操作</strong> 来操作</p>
<p><dfn title="Unicode (多语言), 不区分大小写">2.</dfn>导入数据备份文件</p>
<p>3.修改wp-config.php 文件，增加一行： <strong><span style="color: #ff0000;">define(&#8216;DB_CHARSET&#8217;,'utf8&#8242;);</span></strong></p>
<p>OK，完成！</p>
<p>顺便提一下，低版本数据库导入高版本数据库时，先根据源数据编码指定好新的目标数据库默认编码（通过 <strong>数据库-&gt;操作</strong> 来操作），可以解决大部分数据升级到乱码问题。</p>
]]></content:encoded>
			<wfw:commentRss>http://lee.kometo.com/archives/313/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
