<?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>西红柿爱番茄</title>
	<atom:link href="http://www.ilovejs.net/feed" rel="self" type="application/rss+xml" />
	<link>http://www.ilovejs.net</link>
	<description>到了创造为主的阶段，不忘继续学习</description>
	<lastBuildDate>Thu, 15 Dec 2011 06:18:39 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3</generator>
		<item>
		<title>HTML快捷编写方式</title>
		<link>http://www.ilovejs.net/archives/1551</link>
		<comments>http://www.ilovejs.net/archives/1551#comments</comments>
		<pubDate>Thu, 08 Dec 2011 06:51:06 +0000</pubDate>
		<dc:creator>Supersha</dc:creator>
				<category><![CDATA[(X)HTML]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[HTML]]></category>

		<guid isPermaLink="false">http://www.ilovejs.net/?p=1551</guid>
		<description><![CDATA[礼拜一点小想法，写了个半成品，只供试玩，有心思再来优化解析方式，让它支持更多的语法。 试用地址：http://www.ilovejs.net/lab/makeHTML.html]]></description>
			<content:encoded><![CDATA[<p>礼拜一点小想法，写了个半成品，只供试玩，有心思再来优化解析方式，让它支持更多的语法。<br />
试用地址：<a href="http://www.ilovejs.net/lab/makeHTML.html" target="_blank">http://www.ilovejs.net/lab/makeHTML.html</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.ilovejs.net/archives/1551/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>美化按需加载js文件的形式</title>
		<link>http://www.ilovejs.net/archives/1545</link>
		<comments>http://www.ilovejs.net/archives/1545#comments</comments>
		<pubDate>Sun, 03 Jul 2011 03:41:43 +0000</pubDate>
		<dc:creator>Supersha</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[代码设计]]></category>
		<category><![CDATA[按需加载]]></category>

		<guid isPermaLink="false">http://www.ilovejs.net/?p=1545</guid>
		<description><![CDATA[按需加载，顾名思义就是在用户需要这个功能的时候就初始化这个功能，加载相关的脚本和样式文件等等。普通我们使用的方式，就是在需要的时候，就添加一个文件的url进行加载，并且用一个对象来记录已经加载过的文件。这种方式有些散乱，对于是随意加载的，那倒是不可避免，但是对于一个项目来说，页面的的功能和相应的文件是确定的，那么还是使用上面的方式的话，那么在后期的维护上会比较混乱，增加了成本。 对项目之外的文件加载，使用普通的方式散乱在代码中，也不太合适，那么就需要一个封装的加载器，统一加载文件的接口和调用方式。我下面将要讲的“加载器”，不是传说中的模块化中的加在方式，我更多的是从代码维护方面来考虑，使得一目了然的看到页面本身的功能需要按需加载一些什么文件列表，并且可以标记已经加载的文件，而不会使得url散乱在页面中。 //需要按需加载的内部文件列表映射 mis.classFiles = { 'AjaxEvent': 'includes/ajax.lib.js', 'AjaxRequest': 'includes/request.lib.js', 'colorFade': 'includes/effects.lib.js' } //标记已经include的内部文件 mis.includedFiles = {}; //对内的文件加载 mis.include = &#8230; <a href="http://www.ilovejs.net/archives/1545" class="more-link">了解更多</a>]]></description>
			<content:encoded><![CDATA[<p>
按需加载，顾名思义就是在用户需要这个功能的时候就初始化这个功能，加载相关的脚本和样式文件等等。普通我们使用的方式，就是在需要的时候，就添加一个文件的url进行加载，并且用一个对象来记录已经加载过的文件。这种方式有些散乱，对于是随意加载的，那倒是不可避免，但是对于一个项目来说，页面的的功能和相应的文件是确定的，那么还是使用上面的方式的话，那么在后期的维护上会比较混乱，增加了成本。
</p>
<p>
对项目之外的文件加载，使用普通的方式散乱在代码中，也不太合适，那么就需要一个封装的加载器，统一加载文件的接口和调用方式。我下面将要讲的“加载器”，不是传说中的模块化中的加在方式，我更多的是从代码维护方面来考虑，使得一目了然的看到页面本身的功能需要按需加载一些什么文件列表，并且可以标记已经加载的文件，而不会使得url散乱在页面中。
</p>
<pre class="wp-code-highlight prettyprint">
//需要按需加载的内部文件列表映射
mis.classFiles = {
  'AjaxEvent': 'includes/ajax.lib.js',
  'AjaxRequest': 'includes/request.lib.js',
  'colorFade': 'includes/effects.lib.js'
}

//标记已经include的内部文件
mis.includedFiles = {};

//对内的文件加载
mis.include = function(classname,callback){
  if(mis.includedFiles[classname]){
    callback &amp;amp;&amp;amp; callback();
	  return true;
  }else if(mis.classFiles[classname]){
	  return mis.loadJavaScript(mis.classFiles[classname],callback);
  }else{
	  return false;
  }
}

//标记已经load的内部和外部文件
mis.loadedJavaScript = {}

//无限制的加载file文件
mis.loadJavaScript = function(file,callback){
  callback = callback || function(){};
  if(mis.loadedJavaScript[file]){
	  callback(true);
	  return true;
  }else{
	  var head = document.getElementsByTagName(&amp;quot;head&amp;quot;)[0];
	  var script = head.appendChild(document.createElement(&amp;quot;script&amp;quot;));

    script.onload = script.onreadystatechange = function(){
		  if((!/*@cc_on!@*/0) || (/loaded|complete/).test(script.readyState)){
        script.onreadystatechange = null;
	      mis.loadedJavaScript[file] = true;
	      callback(true);
		  }
	  }

	  script.src = file;
	  return true;
  }
}
</pre>
<p>
代码上没啥技巧，只是让它看起来更直观了点而已。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ilovejs.net/archives/1545/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>爱上过程式编程</title>
		<link>http://www.ilovejs.net/archives/1542</link>
		<comments>http://www.ilovejs.net/archives/1542#comments</comments>
		<pubDate>Mon, 06 Jun 2011 16:01:00 +0000</pubDate>
		<dc:creator>Supersha</dc:creator>
				<category><![CDATA[代码设计]]></category>
		<category><![CDATA[函数式编程]]></category>

		<guid isPermaLink="false">http://www.ilovejs.net/?p=1542</guid>
		<description><![CDATA[在我所负责的产品项目中，在代码编码模式上，使用了函数式编程的方案。约定唯一的命名空间，提供namespace、mixin等基本的语言扩展功能。或者这并没有什么，重要的是一套编码模式。在linux中来说，就是将一个任务细化为一个细小、单一的功能。在我的方案中，基于目前公司开发流程上的约定和线上代码的发布方式，使用一个唯一的命名空间，之后通过这命名空间来维护代码的组织，将一个功能细化，尽量细化到功能单一，保持每一个函数都能够在20行代码以内，并且提供语义化清晰的命名，以及结构化的注释方式，这样代码看起来就整齐有道，极富特点，看起来愉悦，其中一个主要的是提高复用度和较少重复代码和重复功能。 在维护阶段，因为由于维护人员的不同，以前的做法是使用闭包的方式，来包含每一个人新增的代码，保持代码不影响其他的功能。这种方式是可取的，但是这样不容易形成统一的编码方式，在大方式上抓不住，特别在codereview的时候，不能形成统一的阅读方式；而且，使用闭包的方式，在代码复用度等方面基本是难以把握的，基本是代码堆砌，无视之前的实现代码中是否有能够复用的功能函数。使用函数式的方式，那么在维护方面，可以很方便的在原来的代码中复用功能，或者添加、删除功能，因为都在同一个context上下文中，同在一个命名空间下。 使用了函数式编程的方式之后，在我最近的一次项目中，得到了很好的实践，在频繁的需求更改中，由于将功能细化，实际上就是一个大功能，由一堆小功能函数根据不用的条件组织而成。那么在修改功能的时候，只是需要修改其中的小功能函数，或者是删除、增加某个小功能函数，都显得很方便，也很快速，在功能切换上也能够很快的过度。 尽量保持一个函数在20行以内，会让维护者看代码的时候很兴奋。]]></description>
			<content:encoded><![CDATA[<p>
在我所负责的产品项目中，在代码编码模式上，使用了函数式编程的方案。约定唯一的命名空间，提供namespace、mixin等基本的语言扩展功能。或者这并没有什么，重要的是一套编码模式。在linux中来说，就是将一个任务细化为一个细小、单一的功能。在我的方案中，基于目前公司开发流程上的约定和线上代码的发布方式，使用一个唯一的命名空间，之后通过这命名空间来维护代码的组织，将一个功能细化，尽量细化到功能单一，保持每一个函数都能够在20行代码以内，并且提供语义化清晰的命名，以及结构化的注释方式，这样代码看起来就整齐有道，极富特点，看起来愉悦，其中一个主要的是提高复用度和较少重复代码和重复功能。
</p>
<p>
在维护阶段，因为由于维护人员的不同，以前的做法是使用闭包的方式，来包含每一个人新增的代码，保持代码不影响其他的功能。这种方式是可取的，但是这样不容易形成统一的编码方式，在大方式上抓不住，特别在codereview的时候，不能形成统一的阅读方式；而且，使用闭包的方式，在代码复用度等方面基本是难以把握的，基本是代码堆砌，无视之前的实现代码中是否有能够复用的功能函数。使用函数式的方式，那么在维护方面，可以很方便的在原来的代码中复用功能，或者添加、删除功能，因为都在同一个context上下文中，同在一个命名空间下。
</p>
<p>
使用了函数式编程的方式之后，在我最近的一次项目中，得到了很好的实践，在频繁的需求更改中，由于将功能细化，实际上就是一个大功能，由一堆小功能函数根据不用的条件组织而成。那么在修改功能的时候，只是需要修改其中的小功能函数，或者是删除、增加某个小功能函数，都显得很方便，也很快速，在功能切换上也能够很快的过度。
</p>
<p>
尽量保持一个函数在20行以内，会让维护者看代码的时候很兴奋。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ilovejs.net/archives/1542/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>本博客奔向HTML5了</title>
		<link>http://www.ilovejs.net/archives/1530</link>
		<comments>http://www.ilovejs.net/archives/1530#comments</comments>
		<pubDate>Mon, 09 May 2011 16:59:04 +0000</pubDate>
		<dc:creator>Supersha</dc:creator>
				<category><![CDATA[(X)HTML]]></category>
		<category><![CDATA[HTML5]]></category>
		<category><![CDATA[页面重构]]></category>

		<guid isPermaLink="false">http://www.ilovejs.net/?p=1530</guid>
		<description><![CDATA[鉴于目前规划部署项目的静态文件管理和制定页面开发规范，整理出了一个符合项目特点的HTML5规范页面，使用了更有语义化的HTML5标签。趁热打铁，遂将本博客也更新到了HTML5，使得博客的信息内容架构使用更有语义化的标签来展示。比如下图就是博客首页的HTML DOM结构图： 在设计这个结构的时候，在文章列表的标签中停顿斟酌了良久，外层使用了section作为整个内容区域，以区分header和footer，那么里面就是article和aside了，但是文章的列表是一篇篇的文章，从语义话来说，应该用article，而不是使用一系列的div标签，所以果断用了article，外层再使用一个section表示区域。 这次更新中，使用到了section,article,aside,figure,nav,time,hgroup,header,footer等标签，这些标签语义化都比较强，一看即明。 或许在标签的应用上有欠妥的地方，这也算是一种尝试吧，至少，页面布局还是完好的。:)]]></description>
			<content:encoded><![CDATA[<p>
鉴于目前规划部署项目的静态文件管理和制定页面开发规范，整理出了一个符合项目特点的HTML5规范页面，使用了更有语义化的HTML5标签。趁热打铁，遂将本博客也更新到了HTML5，使得博客的信息内容架构使用更有语义化的标签来展示。比如下图就是博客首页的HTML DOM结构图：
</p>
<p><span id="more-1530"></span></p>
<p>
<img src="http://www.ilovejs.net/wp-content/uploads/2011/05/html5-ilovejs1.png" alt="" title="html5-ilovejs" width="476" height="591" class="alignnone size-full wp-image-1533" />
</p>
<p>
在设计这个结构的时候，在文章列表的标签中停顿斟酌了良久，外层使用了section作为整个内容区域，以区分header和footer，那么里面就是article和aside了，但是文章的列表是一篇篇的文章，从语义话来说，应该用article，而不是使用一系列的div标签，所以果断用了article，外层再使用一个section表示区域。
</p>
<p>
这次更新中，使用到了section,article,aside,figure,nav,time,hgroup,header,footer等标签，这些标签语义化都比较强，一看即明。
</p>
<p>
或许在标签的应用上有欠妥的地方，这也算是一种尝试吧，至少，页面布局还是完好的。:)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ilovejs.net/archives/1530/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>优化if~else几种应用场合的代码编写方式，提高代码可读性</title>
		<link>http://www.ilovejs.net/archives/1528</link>
		<comments>http://www.ilovejs.net/archives/1528#comments</comments>
		<pubDate>Sat, 23 Apr 2011 07:14:34 +0000</pubDate>
		<dc:creator>Supersha</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[代码风格]]></category>
		<category><![CDATA[可读性]]></category>

		<guid isPermaLink="false">http://www.ilovejs.net/?p=1528</guid>
		<description><![CDATA[条件表达式通常有两种表现形式，第一种：所有分支都是属于正常行为；第二种：条件表达式提供的答案只有一种是正常行为。其他都是不常见的情况。如果两条分支都是正常行为，就应该使用if~else的条件表达式；如果某个条件极其罕见，就应该单独检查该条件，并在该条件为真时立刻从函数中返回。 function getPayAmount(){ var result; if(isDead) result = deadAmount(); else{ if(isSeparated) result = separatedAmount(); else{ if(isRetired) result = retiredAmount(); else &#8230; <a href="http://www.ilovejs.net/archives/1528" class="more-link">了解更多</a>]]></description>
			<content:encoded><![CDATA[<ol>
<li>
<p>条件表达式通常有两种表现形式，第一种：所有分支都是属于正常行为；第二种：条件表达式提供的答案只有一种是正常行为。其他都是不常见的情况。如果两条分支都是正常行为，就应该使用if~else的条件表达式；如果某个条件极其罕见，就应该单独检查该条件，并在该条件为真时立刻从函数中返回。</p>
<pre class="wp-code-highlight prettyprint">
function getPayAmount(){
  var result;
  if(isDead) result = deadAmount();
  else{
    if(isSeparated) result = separatedAmount();
	else{
	  if(isRetired) result = retiredAmount();
	  else result = normalPayAmount();
	}
  }
  return result;
}
</pre>
<p>可以转化为：</p>
<pre class="wp-code-highlight prettyprint">
function getPayAmount(){
  if(isDead) return deadAmount();
  if(isSeparated) return separatedAmount();
  if(isRedired) return retiredAmount();
  return normalAmount();
}
</pre>
</li>
<li>
<p>在条件表达式的每个分支上有着相同的一段执行代码，这段代码跟分支的逻辑无关的时候，将这段重复代码搬移到条件表达式之外。</p>
<pre class="wp-code-highlight prettyprint">
if(isSpecialDeal()){
  total = price * 0.95;
  send();
}else{
  total = price * 0.98;
  send();
}
</pre>
<p>可以转化为：</p>
<pre class="wp-code-highlight prettyprint">
if(isSpecialDeal()){
  total = price * 0.95;
}else{
  total = price * 0.98;
}
send();
</pre>
</li>
<li>
<p>如果分支条件过于复杂，那么可以将分支条件提炼出来作为一个独立函数，并提供一个语义化更好的名称用于分支判断中。使用它的优势是使得在分支中的代码可读性更好，以至于我不需要知道具体的分支判断条件，就可以理解代码的意图。</p>
<pre class="wp-code-highlight prettyprint">
if(date.before(SUMMER_START) || date.after(SUMMER_END)){
  charge = quantity * _winterRate * _winterServiceCharge;
}else{
  charge = quantity * _summerRate;
}
</pre>
<p>可以转化为：</p>
<pre class="wp-code-highlight prettyprint">
if(notSummer(date)){
  charge = winterCharge(quantity);
}else{
  charge = summerCharge(quantity);
}

function notSummer(date){
  return date.before(SUMMER_START) || date.after(SUMMER_END);
}
function summerCharge(quantity){
  return quantity * _summerRate;
}
function winterCharge(quantity){
  return quantity * _winterRate * _winterServiceCharge;
}
</pre>
</li>
<li>
<p>合并条件表达式。如果有一系列的条件判断，都得到相同的结果；或者嵌套的条件判断。那么将这些条件合并为一个条件表达式，可能的话将这个合并的表达式提炼为一个独立的函数。</p>
<pre class="wp-code-highlight prettyprint">
function disabilityAmount(){
  if(_seniority &amp;lt; 2) return 0;
  if(_monthsDisabled) return 0;
  if(_isPartTime) return 0;
  return 1;
}
</pre>
<p>可以转化为：</p>
<pre class="wp-code-highlight prettyprint">
function disabilityAmount(){
  if(_seniority &amp;lt; 2 || _monthsDisabled || _isPartTime) return 0;
  return 1;
}
</pre>
<p>还可以转化为：</p>
<pre class="wp-code-highlight prettyprint">
function disabilityAmount(){
  if(isNotEligibleForDisability()) return 0;
  return 1;
}

function isNotEligibleForDisability(){
  return _seniority &amp;lt; 2 || _monthsDisabled || _isPartTime;
}
</pre>
</li>
<li>
<p>将条件逻辑反转。有时候使用条件反转的方式，可以很大程度上简化if判断逻辑，特别是在嵌套if判断的时候。</p>
<pre class="wp-code-highlight prettyprint">
function getAdjustedCapital(){
  var result = 0;
  if(_capital &amp;gt; 0){
    if(_intRate &amp;gt; 0 &amp;amp;&amp;amp; _duration &amp;gt; 0){
      result = (_income / _duration) * ADJ_FACTOR;
	}
  }
  return result;
}
</pre>
<p>可以转化为：</p>
<pre class="wp-code-highlight prettyprint">
function getAdjustedCapital(){
  if(_capital &amp;lt;= 0) return 0;
  if(_intRate &amp;lt;= 0 || _duration &amp;lt;=0) return 0;
  return (_income / _duration) * ADJ_FACTOR;
}
</pre>
<p>再简化为：</p>
<pre class="wp-code-highlight prettyprint">
function getAdjustedCapital(){
  if(_capital &amp;lt;= 0 || _intRate &amp;lt;= 0 || _duration &amp;lt;=0) return 0;
  return (_income / _duration) * ADJ_FACTOR;
}
</pre>
</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://www.ilovejs.net/archives/1528/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>浏览器对charset的处理方式</title>
		<link>http://www.ilovejs.net/archives/1526</link>
		<comments>http://www.ilovejs.net/archives/1526#comments</comments>
		<pubDate>Mon, 28 Mar 2011 14:40:56 +0000</pubDate>
		<dc:creator>Supersha</dc:creator>
				<category><![CDATA[性能优化]]></category>
		<category><![CDATA[Charset]]></category>

		<guid isPermaLink="false">http://www.ilovejs.net/?p=1526</guid>
		<description><![CDATA[charset的作用：告诉浏览器，对于服务器端返回来的HTML文件流用何种编码进行解码，从而进行HTML的解析操作。 有三个地方可以设置charset，而且它们的优先级是有顺序的：1、response header；2、HTML文档中的meta；3、浏览器默认的charset声明。那么它们的优先级是如何的呢？ 首先要了解浏览器处理charset的策略：浏览器首先会在服务器返回的response header头中检查是否有charset声明，如果没有，就接着检查HTML head部分的meta标签，是否有声明charset，如果还没有，那么就使用浏览器默认的charset方式进行解码文档流。 在response header头中声明好了charset，那么浏览器在第一时间接收到HTML数据包的时候，就会以这个charset编码进行解码HTML文件流，这种情况下是最快的方式；如果response header头中没找到，那么浏览器会delay解析HTML文档，检查1KB以内的HTML内容是否会包含有charset声明的meta标签。如果还找不到，那么就使用浏览器默认的charset声明进行解码HTML页面，但是这时，已经delay了一些时间了。 如果处理的适当，那么这个delay时间是完全可以避免的，使得HTML页面可以尽可能快的让浏览器使用显示声明的编码进行解码文件流。那就是：在服务端设置好请求内容的charset编码；始终在页面中meta标签内声明charset，当然了，content-type也是十分有必要的。]]></description>
			<content:encoded><![CDATA[<p>
charset的作用：告诉浏览器，对于服务器端返回来的HTML文件流用何种编码进行解码，从而进行HTML的解析操作。
</p>
<p>
有三个地方可以设置charset，而且它们的优先级是有顺序的：1、response header；2、HTML文档中的meta；3、浏览器默认的charset声明。那么它们的优先级是如何的呢？
</p>
<p>
首先要了解浏览器处理charset的策略：浏览器首先会在服务器返回的response header头中检查是否有charset声明，如果没有，就接着检查HTML head部分的meta标签，是否有声明charset，如果还没有，那么就使用浏览器默认的charset方式进行解码文档流。
</p>
<p>
在response header头中声明好了charset，那么浏览器在第一时间接收到HTML数据包的时候，就会以这个charset编码进行解码HTML文件流，这种情况下是最快的方式；如果response header头中没找到，那么浏览器会delay解析HTML文档，检查1KB以内的HTML内容是否会包含有charset声明的meta标签。如果还找不到，那么就使用浏览器默认的charset声明进行解码HTML页面，但是这时，已经delay了一些时间了。
</p>
<p>
如果处理的适当，那么这个delay时间是完全可以避免的，使得HTML页面可以尽可能快的让浏览器使用显示声明的编码进行解码文件流。那就是：在服务端设置好请求内容的charset编码；始终在页面中meta标签内声明charset，当然了，content-type也是十分有必要的。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ilovejs.net/archives/1526/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>一种“职责链”的应用方式</title>
		<link>http://www.ilovejs.net/archives/1519</link>
		<comments>http://www.ilovejs.net/archives/1519#comments</comments>
		<pubDate>Sat, 26 Mar 2011 16:12:24 +0000</pubDate>
		<dc:creator>Supersha</dc:creator>
				<category><![CDATA[代码设计]]></category>
		<category><![CDATA[职责链]]></category>
		<category><![CDATA[设计]]></category>

		<guid isPermaLink="false">http://www.ilovejs.net/?p=1519</guid>
		<description><![CDATA[思路：使用一个储存器，将不同“职责”的处理函数储存起来，之后通过一个统一入口，来处理储存器中的的“职责”函数，将执行有效的结果，立即返回，到此，职责处理完毕。 应用： 在对于传递不同的参数来处理不同的功能； 将功能分“职责”，结构清晰，功能分明； 使用函数的方式，来代替了函数 内部的if逻辑过于负责的判断，可以无限的扩展，最重要的是，可以在不不动原来的函数的基础上，就可以添加其他的“职责”处理函数； /**职责链模式的思维*/ //储存器 var middleware = []; function turning(){ var ret; if(arguments.length &#38;gt; 0){ for(var &#8230; <a href="http://www.ilovejs.net/archives/1519" class="more-link">了解更多</a>]]></description>
			<content:encoded><![CDATA[<p>
<strong>思路</strong>：使用一个储存器，将不同“职责”的处理函数储存起来，之后通过一个统一入口，来处理储存器中的的“职责”函数，将执行有效的结果，立即返回，到此，职责处理完毕。
</p>
<p>
<strong>应用</strong>：
</p>
<ol>
<li>在对于传递不同的参数来处理不同的功能；</li>
<li>将功能分“职责”，结构清晰，功能分明；</li>
<li>使用函数的方式，来代替了函数 内部的if逻辑过于负责的判断，可以无限的扩展，最重要的是，可以在不不动原来的函数的基础上，就可以添加其他的“职责”处理函数；</li>
</ol>
<pre class="wp-code-highlight prettyprint">
/**职责链模式的思维*/

//储存器
var middleware = [];

function turning(){
  var ret;
  if(arguments.length &amp;gt; 0){
    for(var i = 0,len = middleware.length; i &amp;lt; len; i++){
	  //执行每一个“职责”处理函数
      ret = middleware[i].apply(turning,arguments);
	  //如果有返回结果，表示middleware当前item的执行有效，就立即返回结果
	  if(ret){
	    return ret;
	  }
    }
  }
}

//添加“职责”处理函数
turning.init = function(fn){
  middleware.unshift(fn);
}

//在这里可以添加非常多的类似职责的处理函数
turning.init(function(a){
  if(a === &amp;quot;hello&amp;quot;){
    return a + &amp;quot; world&amp;quot;;
  }
});

turning.init(function(a,b){
  if(typeof a === 'number' &amp;amp;&amp;amp; typeof b === 'number'){
    return a + b;
  }
});

//开始应用了
alert(turning(&amp;quot;hello&amp;quot;));
alert(turning(5,9));
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.ilovejs.net/archives/1519/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>权衡之变</title>
		<link>http://www.ilovejs.net/archives/1511</link>
		<comments>http://www.ilovejs.net/archives/1511#comments</comments>
		<pubDate>Sun, 20 Mar 2011 09:05:57 +0000</pubDate>
		<dc:creator>Supersha</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[代码设计]]></category>
		<category><![CDATA[性能优化]]></category>
		<category><![CDATA[模块化]]></category>
		<category><![CDATA[重构]]></category>

		<guid isPermaLink="false">http://www.ilovejs.net/?p=1511</guid>
		<description><![CDATA[《重构&#8211;改善既有代码的设计》这本书是去年买的了，利用晚上空闲时间看了大部分的内容，包括一些重构的技巧、良好代码的特点、代码可读性和提高语义化等。这本书改变了很多我之前所持有的观念，包括代码性能、模块化设计、结构样式逻辑分离等的思维。下面粗略的罗列几点目前自己从这本书中所理解到的其中一些知识： 重构本来就不是一件应该特别拨出时间做的事情，重构应该随时随地进行。 第一次做某件事情时只管去做；第二次做类似的事情会产生反感，但无论如何还是可以去做；第三次再做类似的事，你就应该重构。 &#8212;&#8212;“事不过三，三则重构。” 只要将相对独立的代码从大型函数中提炼出来，就可以大大提高代码的可读性。 不单只让函数能够功能单一的执行，同时也需要让一个类也只需要明确的做一件事情，或者只是对各个功能的集合（代理、命名空间）。 在该函数最常引用的类中建立一个有着类似行为的新函数，将旧函数变成一个单纯的委托函数，或者将旧函数完全移除。根据这个函数与哪个对象的交流比较多，决定将函数移动的位置。 抽象函数可以是多重的，将可复用的代码尽量的抽象它，在抽象后的函数中，又需要对函数进行进一步的思考，是否功能还可以更加的细化，让功能函数为更多的其他函数、对象、类所复用。距离组织一个库来说：core大部分只提供核心类（核心对象）的扩展、继承机制、底层内置功能的扩充、封装机制、兼容性判断机制、对象版本管理机制等，这就算是一个core最细化的抽象。 一个类应该是一个清楚的抽象，处理一些明确的责任。 “封装”意味着每个对象都应该尽可能少了解系统的其他部分，如此一来，一旦发生变化，需要了解这一变化的对象和函数就会比较少，这会使变化比较容易进行。 有几个原因造成我喜欢简短而命名良好的函数：首先，如果每个函数的粒度都很小，那么函数被复用的机会就更大；其次，这会使高层函数读起来就像一系列注释；再次，如果函数都是细粒度，那么函数的覆写也会更容易些。 在函数的命名上，长度不是问题，关键在于函数名称和函数本体之间的语义距离。 创造一个新函数，根据这个函数的意图来对它命名（以它“做什么”来命名，而不是以它“怎么做”命名），但是如果你想不出一个更有意义的名称，那就别动。 如果在提炼的函数中需要一些原来旧函数中的局部变量数据，那么就将这些局部变量数据通过参数的形式传递过去。 当一个函数有参数的时候，在函数体里就尽量不要去修改参数的值，不管是通过值还是引用传递进来的，除非有另外特定的目的。 将函数细粒化为一个个功能单一的函数，再调用这些函数，这必然造成了性能上更多的耗费，但是这跟后期的维护、以及代码的可读性等等相比，或许还是值得这么做的。 永远不要认为你写的代码只是自己看的而已，要想到新来的人接手你的这些代码的时候，他们看你的代码，是否能够很愉快的接受并理清整个思路。不要把这个维护代码的痛苦留给接手你的人。不管你是通过更多的注释还是重构代码的方式来解决代码的可维护性的问题，都要想到这一点。 在分解一个函数的时候，我的思路是：需求是什么 &#8211;> 需求的功能有哪些 &#8230; <a href="http://www.ilovejs.net/archives/1511" class="more-link">了解更多</a>]]></description>
			<content:encoded><![CDATA[<p>
《<a href="http://product.dangdang.com/product.aspx?product_id=20801315">重构&#8211;改善既有代码的设计</a>》这本书是去年买的了，利用晚上空闲时间看了大部分的内容，包括一些重构的技巧、良好代码的特点、代码可读性和提高语义化等。这本书改变了很多我之前所持有的观念，包括代码性能、模块化设计、结构样式逻辑分离等的思维。下面粗略的罗列几点目前自己从这本书中所理解到的其中一些知识：
</p>
<blockquote><p>重构本来就不是一件应该特别拨出时间做的事情，重构应该随时随地进行。<br />
第一次做某件事情时只管去做；第二次做类似的事情会产生反感，但无论如何还是可以去做；第三次再做类似的事，你就应该重构。 &#8212;&#8212;“事不过三，三则重构。”
</p></blockquote>
<p><span id="more-1511"></span></p>
<ol>
<li>只要将相对独立的代码从大型函数中提炼出来，就可以大大提高代码的可读性。</li>
<li>不单只让函数能够功能单一的执行，同时也需要让一个类也只需要明确的做一件事情，或者只是对各个功能的集合（代理、命名空间）。</li>
<li>在该函数最常引用的类中建立一个有着类似行为的新函数，将旧函数变成一个单纯的委托函数，或者将旧函数完全移除。根据这个函数与哪个对象的交流比较多，决定将函数移动的位置。</li>
<li>抽象函数可以是多重的，将可复用的代码尽量的抽象它，在抽象后的函数中，又需要对函数进行进一步的思考，是否功能还可以更加的细化，让功能函数为更多的其他函数、对象、类所复用。距离组织一个库来说：core大部分只提供核心类（核心对象）的扩展、继承机制、底层内置功能的扩充、封装机制、兼容性判断机制、对象版本管理机制等，这就算是一个core最细化的抽象。</li>
<li>一个类应该是一个清楚的抽象，处理一些明确的责任。</li>
<li>“封装”意味着每个对象都应该尽可能少了解系统的其他部分，如此一来，一旦发生变化，需要了解这一变化的对象和函数就会比较少，这会使变化比较容易进行。</li>
<li>有几个原因造成我喜欢简短而命名良好的函数：首先，如果每个函数的粒度都很小，那么函数被复用的机会就更大；其次，这会使高层函数读起来就像一系列注释；再次，如果函数都是细粒度，那么函数的覆写也会更容易些。<br />
在函数的命名上，长度不是问题，关键在于函数名称和函数本体之间的语义距离。<br />
创造一个新函数，根据这个函数的意图来对它命名（以它“做什么”来命名，而不是以它“怎么做”命名），但是如果你想不出一个更有意义的名称，那就别动。<br />
如果在提炼的函数中需要一些原来旧函数中的局部变量数据，那么就将这些局部变量数据通过参数的形式传递过去。
</li>
<li>当一个函数有参数的时候，在函数体里就尽量不要去修改参数的值，不管是通过值还是引用传递进来的，除非有另外特定的目的。</li>
<li>将函数细粒化为一个个功能单一的函数，再调用这些函数，这必然造成了性能上更多的耗费，但是这跟后期的维护、以及代码的可读性等等相比，或许还是值得这么做的。</li>
<li>永远不要认为你写的代码只是自己看的而已，要想到新来的人接手你的这些代码的时候，他们看你的代码，是否能够很愉快的接受并理清整个思路。不要把这个维护代码的痛苦留给接手你的人。不管你是通过更多的注释还是重构代码的方式来解决代码的可维护性的问题，都要想到这一点。</li>
<li>在分解一个函数的时候，我的思路是：需求是什么 &#8211;> 需求的功能有哪些 &#8211;> 团队开发方式是如何的 &#8211;> 在当前功能点下，罗列函数层级的功能点，并根据这些功能点进行整合，即是高内聚，低耦合。之后逐一组建函数。<br />
明白需求是什么，这个是做开发的最先需要了解清楚的，这点无可厚非；在这个需求下面，需要实现一些什么功能，这个是需要根据需求来分析出来的，之后的就是根据自己团队的代码开发模式，并逐步将需求的功能点，细化到代码层级的功能点，将功能抽象出来，提高代码的可复用度。
</li>
</ol>
<p>
自己之前所遵守的高性能、微小代码量、满脑子模块化、保持结构样式逻辑高度分离等的思维，再次进行了权衡的颠覆。对于代码，性能重要，但是人也能很容易的看懂这也重要。一个项目，到底是开发新功能的需求大，还是维护、优化项目的需求更多，这个就需要在高速开发和提高代码的可读性和较少维护成本进行权衡。
</p>
<p>
使用工具进行页面拼装的方式，固然可以提高开发效率，这对于一些促销页面开发、或者是有PM、运营所自定义页面来说，确实有必要。但是这些都是辅助页面，核心产品才是主要关注点，核心产品一般不会轻易的推倒重来，而是不断的进行优化、功能升级、新功能上线等。为此，对于开发者来说，除了代码能够给电脑读，还能很好的给其他开发者读懂，这个有必要。在性能和代码量上或许可以做个权衡，也或者可以从其他方面进行优化来弥补这方面的损失。
</p>
<p>
模块化，有时候真的很少用到，除非是大站点，从整体架构考虑，提高功能的聚合度和整体统一。在一些细小项目、功能开发中，用到更多的还是借助于统一的库，进行二次的功能开发，封装为适合该项目、功能的功能函数集。就如上面《重构》书中所述，当这个功能为几个项目、功能所使用的时候，那么就有必要抽象出来，作为一个模块。但是，对于模块，从现阶段来说，它已经不是跟以前一样，只是一个js文件，它所要负责是它的功能范围内的HTML、CSS、JS，对于页面来说，我无需关心这个模块有啥，我只需要调用这个模块的接口，加载这个模块，那么我的页面中就有了这个模块最基本的功能，再复杂点，就是提供给模块进行扩展的接口，在模块的基础上，进行自定义结构、样式、逻辑。
</p>
<p>
所以，对于模块化，要区分好Moudle，Utilities，功能函数的差别。Util只是对功能逻辑的封装，加载这个js文件，就可以直接使用它所提供的逻辑方法，它并不涉及到样式、结构，只是一个逻辑。功能函数更多的是存在于页面中的，如果使用度够高，那么就会成为Util的一部分。功能函数更多的是在已有的库的基础上进行的二次封装、抽象，提供给其他的功能直接调用。将页面中都会用到的功能进行抽取，作为一个独立的功能函数，通过参数来体现功能的差异。
</p>
<p>
在结构、样式、逻辑上，这个并没有完全的分离的界限，很多时候都需要看功能的具体需求，不能完全要求分离结构和逻辑，就使得在逻辑方面需要做很多的动态创建结构的工作。这就需要权衡：如何使用正确的HTML标签，标签能否提供一些辅助的信息，来简化逻辑的操作和代码量。适合在标签上能做的事情，就让标签来提供。“各司其职”的折中是互相辅助。
</p>
<p>
想得有点多了，需要慢慢学习和实践~~</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ilovejs.net/archives/1511/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>检测link元素加载完成的方式</title>
		<link>http://www.ilovejs.net/archives/1505</link>
		<comments>http://www.ilovejs.net/archives/1505#comments</comments>
		<pubDate>Sun, 20 Mar 2011 06:35:59 +0000</pubDate>
		<dc:creator>Supersha</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[style]]></category>
		<category><![CDATA[异步加载]]></category>

		<guid isPermaLink="false">http://www.ilovejs.net/?p=1505</guid>
		<description><![CDATA[检测外联js是否加载完毕，这个相对来说比较简单，只需要处理onload和onreadystatechange在非IE和IE下做兼容，但是需要检测外联的CSS文件是否加载完毕，这个就有点恶心了，大致分成了三类：IE和Opera；Chrome和Safari、FF，这时候FF没有跟着大部队走了，这或许也是FF中的一个bug。 最理想的方式，无非就是统一使用onload来检测link元素是否加载完毕。但是事不与程序猿人愿~ 但是兼容办法还是有的。 在IE、Opera下，可以直接使用onload、onreadystatechange这两种方式都可以检测link元素是否加载完成，跟检测script一样的原理。 在Chrome、Safari等基于Webkit内核的浏览器下，估计就要监控document.styleSheets.length的变化了。Webkit内核的浏览器在处理document.styleSheets.length的方式是这样的，当加载完了一个link之后，length就会加1，那么这样的话，就可以使用setInterval的方式来检测length的变化了，对于同时检测多个link是否加载完成的方式也可以利用这个，看length增加了多少。《测试用例》示例如下： [javascript] var link = document.createElement(&#34;link&#34;); var cn = document.styleSheets.length; var ti = setInterval(function() { if &#8230; <a href="http://www.ilovejs.net/archives/1505" class="more-link">了解更多</a>]]></description>
			<content:encoded><![CDATA[<p>
检测外联js是否加载完毕，这个相对来说比较简单，只需要处理onload和onreadystatechange在非IE和IE下做兼容，但是需要检测外联的CSS文件是否加载完毕，这个就有点恶心了，大致分成了三类：IE和Opera；Chrome和Safari、FF，这时候FF没有跟着大部队走了，这或许也是FF中的一个bug。
</p>
<p>
最理想的方式，无非就是统一使用onload来检测link元素是否加载完毕。但是事不与程序猿人愿~ 但是兼容办法还是有的。
</p>
<p>
在IE、Opera下，可以直接使用onload、onreadystatechange这两种方式都可以检测link元素是否加载完成，跟检测script一样的原理。
</p>
<p>
在Chrome、Safari等基于Webkit内核的浏览器下，估计就要监控document.styleSheets.length的变化了。Webkit内核的浏览器在处理document.styleSheets.length的方式是这样的，当加载完了一个link之后，length就会加1，那么这样的话，就可以使用setInterval的方式来检测length的变化了，对于同时检测多个link是否加载完成的方式也可以利用这个，看length增加了多少。《<a href="http://www.ilovejs.net/lab/css/loadCSS-Webkit.html">测试用例</a>》示例如下：
</p>
<p>[javascript]<br />
var link = document.createElement(&quot;link&quot;);<br />
var cn = document.styleSheets.length;</p>
<p>var ti = setInterval(function() {<br />
  if (document.styleSheets.length &gt; cn) {<br />
    alert(&quot;CSS loaded&quot;);<br />
    clearInterval(ti);<br />
  }<br />
}, 10);</p>
<p>link.href=&quot;http://www.ilovejs.net/lab/css.php&quot;;<br />
link.rel = &quot;stylesheet&quot;;<br />
document.getElementsByTagName(&quot;head&quot;)[0].appendChild(link);<br />
[/javascript]</p>
<p>
但是在Firefox下，情况就有些恶心了，所使用到的方式跟上面的两类浏览器的处理方式都不太相同。对于document.styleSheets.length的处理也不同于Webkit，它的处理方式是只要link元素一附加到document之后，length就会立即加1，而不管css文件是否加载完毕（测试用例如上面的链接）。为此，对于Firefox的处理方式，使用style标签，而不是link，并且使用传统的@import的方式，通过判断style.sheet.cssRules是否存在来检测css文件是否加载完成，具体如下所示《<a href="http://www.ilovejs.net/lab/css/loadCSS-FF.html">测试用例</a>》：
</p>
<p>[javascript]<br />
var head = document.getElementsByTagName(&quot;head&quot;)[0];</p>
<p>var style = document.createElement(&#8216;style&#8217;);<br />
//加载css.php文件，需要2秒之后才会返回响应内容<br />
style.textContent = &#8216;@import &quot;http://www.ilovejs.net/lab/css/css.php&quot;&#8217;;<br />
style.rel=&quot;stylesheet&quot;;</p>
<p>var fi = setInterval(function() {<br />
  try {<br />
    style.sheet.cssRules; // 这句是关键，在css加载完成的时候，style元素就会有这么个对象。</p>
<p>	alert(&quot;CSS loaded&quot;);</p>
<p>    clearInterval(fi);</p>
<p>  } catch (e){}</p>
<p>}, 10);  </p>
<p>head.appendChild(style);<br />
[/javascript]</p>
<p>
为此，想要写一个兼容性的检测CSS文件是否加载完成的代码，估计看起来会比较丑陋，差异大，处理的方式各异，期待onload统一的那一天咯~~</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ilovejs.net/archives/1505/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>编码啐念</title>
		<link>http://www.ilovejs.net/archives/1496</link>
		<comments>http://www.ilovejs.net/archives/1496#comments</comments>
		<pubDate>Thu, 24 Feb 2011 13:41:44 +0000</pubDate>
		<dc:creator>Supersha</dc:creator>
				<category><![CDATA[啐啐念]]></category>
		<category><![CDATA[代码质量]]></category>
		<category><![CDATA[编码]]></category>
		<category><![CDATA[编码习惯]]></category>

		<guid isPermaLink="false">http://www.ilovejs.net/?p=1496</guid>
		<description><![CDATA[最近发现自己的代码产出率下降多了，在编码期间会不断的去推敲代码是否合适，是否做到了该有的优化、语意化、代码分离、提高代码复用、增强代码的可读性。该让HTML做的事情，就尽量让HTML去做；能用HTML、CSS去帮助JS一起实现的功能，就尽量依赖于HTML、CSS，来减少JS的代码量，同时也不失代码的分离，各司其职，互相独立，这或许是一个极端，让三者（HTML、CSS、JS）互相帮助，互相辅助（减少JS动态生成HTML的代码；较少多个样式设置的次数；减少HTML中包含CSS、JS代码；尽量少去删除和增加DOM树的节点；是用innerHTML来代替内容，还是简单的使用显示隐藏，或者replaceChild代替原来的节点。。。），而又不能互相在代码上互相嵌入，依赖过大，保持必要的分离，从而达到一个平衡的状态，那么在性能、代码量等等上就是一个很好的权衡。 有句话说的好：“当你感觉一个功能的代码已经无法再增加和删除代码了，那么就行了”。但是这种感觉以及代码的质量的如何，那就是个人的功底和经验是否丰富了。自我感觉良好有时候也是一种自我封闭，应该保持学习和改变的心态。 但是这样做的后果很明显，项目开发时间拉长了一些（除非在相同的开发时间里，加班加点完成），所以在代码质量、开发时间上是不能成正比的，需要一个权衡。而这个权衡很大的一部分在于上头对于代码质量是否有一定程度的要求，而在开发时间上能够尽量的放宽，当然开发者本身的功底对于实现该需求在质量和时间上是否能够达到一个平衡，也是其中的一点。关键还是看上头是否重视该需求吧。 对于一些小需求来说，可能要求是尽快的产出，上头对此的重视程度不高，只要实现了功能，对于是否影响用户体验没有过大的要求，那么这样也去反复推敲代码的质量，是否有必要呢？更多的是从习惯以及对自己以后的发展负责去考虑这个问题了，养成一定的良好的开发习惯，这或许对自己本身来说是非常重要的。]]></description>
			<content:encoded><![CDATA[<p>
最近发现自己的代码产出率下降多了，在编码期间会不断的去推敲代码是否合适，是否做到了该有的优化、语意化、代码分离、提高代码复用、增强代码的可读性。该让HTML做的事情，就尽量让HTML去做；能用HTML、CSS去帮助JS一起实现的功能，就尽量依赖于HTML、CSS，来减少JS的代码量，同时也不失代码的分离，各司其职，互相独立，这或许是一个极端，让三者（HTML、CSS、JS）互相帮助，互相辅助（减少JS动态生成HTML的代码；较少多个样式设置的次数；减少HTML中包含CSS、JS代码；尽量少去删除和增加DOM树的节点；是用innerHTML来代替内容，还是简单的使用显示隐藏，或者replaceChild代替原来的节点。。。），而又不能互相在代码上互相嵌入，依赖过大，保持必要的分离，从而达到一个平衡的状态，那么在性能、代码量等等上就是一个很好的权衡。
</p>
<p>
有句话说的好：“当你感觉一个功能的代码已经无法再增加和删除代码了，那么就行了”。但是这种感觉以及代码的质量的如何，那就是个人的功底和经验是否丰富了。自我感觉良好有时候也是一种自我封闭，应该保持学习和改变的心态。
</p>
<p>
但是这样做的后果很明显，项目开发时间拉长了一些（除非在相同的开发时间里，加班加点完成），所以在代码质量、开发时间上是不能成正比的，需要一个权衡。而这个权衡很大的一部分在于上头对于代码质量是否有一定程度的要求，而在开发时间上能够尽量的放宽，当然开发者本身的功底对于实现该需求在质量和时间上是否能够达到一个平衡，也是其中的一点。关键还是看上头是否重视该需求吧。
</p>
<p>
对于一些小需求来说，可能要求是尽快的产出，上头对此的重视程度不高，只要实现了功能，对于是否影响用户体验没有过大的要求，那么这样也去反复推敲代码的质量，是否有必要呢？更多的是从习惯以及对自己以后的发展负责去考虑这个问题了，养成一定的良好的开发习惯，这或许对自己本身来说是非常重要的。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ilovejs.net/archives/1496/feed</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Build程序升级</title>
		<link>http://www.ilovejs.net/archives/1488</link>
		<comments>http://www.ilovejs.net/archives/1488#comments</comments>
		<pubDate>Wed, 09 Feb 2011 13:10:48 +0000</pubDate>
		<dc:creator>Supersha</dc:creator>
				<category><![CDATA[开发工具]]></category>
		<category><![CDATA[Perl Build]]></category>
		<category><![CDATA[代码合并]]></category>
		<category><![CDATA[自动化]]></category>

		<guid isPermaLink="false">http://www.ilovejs.net/?p=1488</guid>
		<description><![CDATA[出于这样的一种开发想法：页面中可能会包含很多script、style行内标签用于各种细粒化控制的目的，在发布的时候，这些行内的script标签的代码并没有自动的合并为一个，这样导致已发布的页面中script标签过多，而且这样代码看起来也比较凌乱。这只是从代码组织方面的考虑，还有一个想法就是多人维护一个页面的代码，在添加新功能的时候，就无须考虑是否从已有的script标签中添加代码，放心的使用一个独立的script标签来编写代码，在开发编译之后，会将页面的这些script合并为一个。尽可能的减少赘余的script、style标签。 但是这样需要考虑这样的一个问题（特别是script）：执行顺序。为此，添加了一个combine的标识来标识哪些script、style需要被合并，可以自定义。下面是一个示例html的语法页面： [html] &#60;!doctype html&#62; &#60;html&#62; &#60;c::head&#62; &#60;meta charset=&#34;utf-8&#34;&#62; &#60;meta http-equiv=&#34;X-UA-Compatible&#34; content=&#34;IE=Edge&#34;&#62; &#60;meta http-equiv=&#34;X-Frame-Options&#34; content=&#34;DENY&#34; /&#62; &#60;title&#62;Template&#60;/title&#62; &#60;script combine compress&#62; &#8230; <a href="http://www.ilovejs.net/archives/1488" class="more-link">了解更多</a>]]></description>
			<content:encoded><![CDATA[<p>
出于这样的一种开发想法：页面中可能会包含很多script、style行内标签用于各种细粒化控制的目的，在发布的时候，这些行内的script标签的代码并没有自动的合并为一个，这样导致已发布的页面中script标签过多，而且这样代码看起来也比较凌乱。这只是从代码组织方面的考虑，还有一个想法就是多人维护一个页面的代码，在添加新功能的时候，就无须考虑是否从已有的script标签中添加代码，放心的使用一个独立的script标签来编写代码，在开发编译之后，会将页面的这些script合并为一个。尽可能的减少赘余的script、style标签。
</p>
<p><span id="more-1488"></span></p>
<p>
但是这样需要考虑这样的一个问题（特别是script）：执行顺序。为此，添加了一个combine的标识来标识哪些script、style需要被合并，可以自定义。下面是一个示例html的语法页面：
</p>
<p>[html]<br />
&lt;!doctype html&gt;<br />
&lt;html&gt;<br />
&lt;c::head&gt;<br />
&lt;meta charset=&quot;utf-8&quot;&gt;<br />
&lt;meta http-equiv=&quot;X-UA-Compatible&quot; content=&quot;IE=Edge&quot;&gt;<br />
&lt;meta http-equiv=&quot;X-Frame-Options&quot; content=&quot;DENY&quot; /&gt;<br />
&lt;title&gt;Template&lt;/title&gt;<br />
&lt;script combine compress&gt;<br />
/* inline script */<br />
function test(){<br />
  return &quot;hello world&quot;;<br />
}<br />
&lt;/script&gt;<br />
&lt;!&#8211;&lt;link rel=&quot;stylesheet&quot; href=&quot;/wp-content/c/style.css&quot;&gt;&#8211;&gt;<br />
&lt;style combine compress&gt;<br />
/* inline css */<br />
body{<br />
  background:#c00;<br />
  color:#fff;<br />
}<br />
h1,h2,h3,h4{<br />
  font-size:12px;<br />
  font-weight:normal;<br />
}<br />
&lt;/style&gt;<br />
&lt;/c::head&gt;<br />
&lt;c::body&gt;<br />
&lt;!&#8211; &lt;script src=&quot;yui-debug.js&quot;&gt;&lt;/script&gt; &#8211;&gt;</p>
<p>&lt;style combine compress&gt;<br />
/* inline css */<br />
input{<br />
  width:200px;<br />
}<br />
div{<br />
  border:1px solid #ccc;<br />
}<br />
&lt;/style&gt;</p>
<p>&lt;script combine compress&gt;</p>
<p>var addMethod = function(obj,name,fn){<br />
  var old = obj[name];<br />
  obj[name] = function(){<br />
    if(fn.length == arguments.length){<br />
	  return fn.apply(this,arguments);<br />
	}else if(typeof old == &quot;function&quot;){<br />
	  return old.apply(this,arguments);<br />
	}<br />
  }<br />
}</p>
<p>var user = {};</p>
<p>addMethod(user,&quot;find&quot;,function(){<br />
  return &quot;no arguments&quot;;<br />
});</p>
<p>addMethod(user,&quot;find&quot;,function(a){<br />
  return &quot;arguments length&quot; + arguments.length;<br />
});</p>
<p>addMethod(user,&quot;find&quot;,function(a,b){<br />
  return &quot;arguments length&quot; + arguments.length;<br />
});</p>
<p>//var user = new Users();</p>
<p>alert(user.find());<br />
alert(user.find(&quot;123&quot;));<br />
alert(user.find(&quot;123&quot;,&quot;456&quot;));</p>
<p>&lt;/script&gt;<br />
&lt;/c::body&gt;<br />
&lt;/html&gt;<br />
[/html]</p>
<p>
编译之后，就成下面的样子了：
</p>
<p>[html]<br />
&lt;!doctype html&gt;<br />
&lt;html&gt;<br />
&lt;head&gt;&lt;meta charset=utf-8&gt;&lt;meta http-equiv=X-UA-Compatible content=&quot;IE=Edge&quot;&gt;&lt;meta http-equiv=X-Frame-Options content=DENY /&gt;&lt;title&gt;Template&lt;/title&gt;&lt;style&gt;body{background:#c00;color:#fff}h1,h2,h3,h4{font-size:12px;font-weight:normal}input{width:200px}div{border:1px solid #ccc}&lt;/style&gt;&lt;/head&gt;<br />
&lt;body&gt;&lt;script&gt;function test(){return&quot;hello world&quot;};var addMethod=function(d,b,c){var a=d[b];d[b]=function(){if(c.length==arguments.length){return c.apply(this,arguments)}else{if(typeof a==&quot;function&quot;){return a.apply(this,arguments)}}}};var user={};addMethod(user,&quot;find&quot;,function(){return&quot;no arguments&quot;});addMethod(user,&quot;find&quot;,function(b){return&quot;arguments length&quot;+arguments.length});addMethod(user,&quot;find&quot;,function(d,c){return&quot;arguments length&quot;+arguments.length});alert(user.find());alert(user.find(&quot;123&quot;));alert(user.find(&quot;123&quot;,&quot;456&quot;));&lt;/script&gt;&lt;/body&gt;<br />
&lt;/html&gt;<br />
[/html]</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ilovejs.net/archives/1488/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>压缩HTML的意义</title>
		<link>http://www.ilovejs.net/archives/1475</link>
		<comments>http://www.ilovejs.net/archives/1475#comments</comments>
		<pubDate>Tue, 18 Jan 2011 01:45:53 +0000</pubDate>
		<dc:creator>Supersha</dc:creator>
				<category><![CDATA[(X)HTML]]></category>
		<category><![CDATA[性能优化]]></category>
		<category><![CDATA[HTML压缩]]></category>

		<guid isPermaLink="false">http://www.ilovejs.net/?p=1475</guid>
		<description><![CDATA[对于压缩HTML的好与坏、利与弊，网上也已经谈论的很多，自己也搜集了一下，毕竟自己最近也在做这样的一个工具来压缩HTML代码，提出一下自己的见解以及一些设想。 支持不压缩HTML的原因有这样的一些考虑：去掉换行、多个空白之后可能会对样式有影响；pre标签形式压缩之后会失去原有的意义；IE条件注释不能够删除；只是压缩空白和注释收益不大，特别是在gzip压缩之后；压缩了代码，看源码不方便；性价比低，付出的技术成本跟收到的效果不成正比&#8230;。原因很多哎，所以造成了大部分的站点对于HTML都是未压缩的状态发布了。为什么不压缩 HTML 这几天思前想后，HTML压缩的意义在哪里？ 如果纯粹是压缩注释、空格、换行，并且在开启Gzip压缩的情况下，那么这些确实很有限制，如果没有gzip压缩呢？开启了gzip压缩，但是被一些防火墙软件、杀毒软件把请求头的Accept-Encoding给短路了呢？那么这样的话，页面的HTML代码估计要大20%了，如果这20%是对于一个日均pv大的站点，可以估量这个宽带的花费，收益是很明显的，Who’s not getting gzip?。 我们可以开启Gzip，但是不能够完全相信用户的浏览器得到的都是gzip压缩后的代码，客户端的环境是复杂的，如果没有gzip压缩的话，页面的代码量跟压缩HTML之后的代码量，需要一个具体的数据来权衡。 空白、注释这些在浏览器是会去解析的，解析为空白节点、注释节点，多个空格需要解析为一个空格节点，这些都是会耗费浏览器的资源的。我相信，在普遍的浏览器解析HTML文档流的时候，一行的解析总比解析几行来的快，就像解析CSS规则一样，解析一条规则比解析几条规则总来的快。一点点猜测HTML的解析原理。。。 但是又不能够一股脑门的去压缩全部的HTML代码，或者使用手工的方式去压缩，这个成本确实会很大。如果只是压缩空格、注释，这个收益也确实会很小。这就应该使用一个工具来最大化的压缩HTML代码，使用词法分析的方式，对于一些浏览器默认的HTML属性，但是在开发过程中又显示声明了，那么这些就是可以清除的；更疯狂的可以对属性的单双引号去除（不过这个对属性值带有单双引号可能会造成问题，需要衡量）；一些不必要的meta标签的声明的缩减或者删除，比如： &#60;meta name=”robots” content=”index&#124;follow”&#62; 替换为&#60;meta name=”robots” content=”all”&#62; 小日本对这两个meta标签看的很重： &#60;meta http-equiv=”Content-Style-Type” &#8230; <a href="http://www.ilovejs.net/archives/1475" class="more-link">了解更多</a>]]></description>
			<content:encoded><![CDATA[<p>
对于压缩HTML的好与坏、利与弊，网上也已经谈论的很多，自己也搜集了一下，毕竟自己最近也在做这样的一个工具来压缩HTML代码，提出一下自己的见解以及一些设想。
</p>
<p>
支持不压缩HTML的原因有这样的一些考虑：去掉换行、多个空白之后可能会对样式有影响；pre标签形式压缩之后会失去原有的意义；IE条件注释不能够删除；只是压缩空白和注释收益不大，特别是在gzip压缩之后；压缩了代码，看源码不方便；性价比低，付出的技术成本跟收到的效果不成正比&#8230;。原因很多哎，所以造成了大部分的站点对于HTML都是未压缩的状态发布了。<a  href="http://lifesinger.org/blog/2010/05/why-dont-compress-html/">为什么不压缩 HTML</a>
</p>
<p>
这几天思前想后，HTML压缩的意义在哪里？
</p>
<p><span id="more-1475"></span></p>
<p>
如果纯粹是压缩注释、空格、换行，并且在开启Gzip压缩的情况下，那么这些确实很有限制，如果没有gzip压缩呢？开启了gzip压缩，但是被一些防火墙软件、杀毒软件把请求头的Accept-Encoding给短路了呢？那么这样的话，页面的HTML代码估计要大20%了，如果这20%是对于一个日均pv大的站点，可以估量这个宽带的花费，收益是很明显的，<a  href="http://www.stevesouders.com/blog/2009/11/11/whos-not-getting-gzip/">Who’s not getting gzip?</a>。
</p>
<p>
我们可以开启Gzip，但是不能够完全相信用户的浏览器得到的都是gzip压缩后的代码，客户端的环境是复杂的，如果没有gzip压缩的话，页面的代码量跟压缩HTML之后的代码量，需要一个具体的数据来权衡。
</p>
<p>
空白、注释这些在浏览器是会去解析的，解析为空白节点、注释节点，多个空格需要解析为一个空格节点，这些都是会耗费浏览器的资源的。我相信，在普遍的浏览器解析HTML文档流的时候，一行的解析总比解析几行来的快，就像解析CSS规则一样，解析一条规则比解析几条规则总来的快。一点点猜测HTML的解析原理。。。
</p>
<p>
但是又不能够一股脑门的去压缩全部的HTML代码，或者使用手工的方式去压缩，这个成本确实会很大。如果只是压缩空格、注释，这个收益也确实会很小。这就应该使用一个工具来最大化的压缩HTML代码，使用词法分析的方式，对于一些浏览器默认的HTML属性，但是在开发过程中又显示声明了，那么这些就是可以清除的；更疯狂的可以对属性的单双引号去除（不过这个对属性值带有单双引号可能会造成问题，需要衡量）；一些不必要的meta标签的声明的缩减或者删除，比如：<br />
&lt;meta name=”robots” content=”index|follow”&gt;<br />
替换为&lt;meta name=”robots” content=”all”&gt;<br />
小日本对这两个meta标签看的很重：<br />
&lt;meta http-equiv=”Content-Style-Type” content=”text/css”&gt;<br />
&lt;meta http-equiv=”Content-Script-Type” content=”text/javascript”&gt;<br />
对于咱们，可能是完全没有必要的；<br />
对于行内样式规则的最后一个分号进行清理等等，嵌入到真正的代码中进行优化，效果还是可观的。
</p>
<p>
而对于压缩的方式，可以支持标识一定范围内的标签进行压缩，而不是一股脑门的对整个HTML文档进行压缩，这样就可以重复的自定义HTML压缩，而对于有pre、压缩之后会出现样式错误（这纯粹是利用空格来展示样式的错误方式导致的，可以从技术上去尽量避免这个事情，因为很容易留下个暗坑让人踩）等问题。
</p>
<p>
压缩之后，对浏览器解析HTML的性能、代码量、减少宽带上收益会更大，性价比也高。
</p>
<p>
但是，这个需要工具，替人干活的工具的出现。。。。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ilovejs.net/archives/1475/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>在Ipod Safari下开发有一点点感</title>
		<link>http://www.ilovejs.net/archives/1459</link>
		<comments>http://www.ilovejs.net/archives/1459#comments</comments>
		<pubDate>Sun, 16 Jan 2011 14:10:33 +0000</pubDate>
		<dc:creator>Supersha</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Ipod Safari]]></category>
		<category><![CDATA[UIX widget system]]></category>
		<category><![CDATA[事件]]></category>
		<category><![CDATA[收藏夹]]></category>

		<guid isPermaLink="false">http://www.ilovejs.net/?p=1459</guid>
		<description><![CDATA[最近突然脑子一热，Read It Later好、Instapaper也好，保存的网页都是在别人的服务器上，使用别人的工具来浏览，总感觉受牵制，干脆自己倒腾一个这样的工具，把数据提交到自己的网站空间里，之后使用Ipod Touch来看，这个更有保障，功能其实也就需要一个保存网页的URL并且在空闲的时候浏览，简单的一个收藏夹。并且可以顺便尝试使用Youtube的UIX事件机制。 下面是简单的一个UIX事件绑定方式： [javascript] // UIX system var UIX = UIX &#124;&#124; { &#34;registry&#34;:{}, &#34;register&#34;:function(type,uixes){ if(!this.registry[type]){ this.registry[type]={}; } &#8230; <a href="http://www.ilovejs.net/archives/1459" class="more-link">了解更多</a>]]></description>
			<content:encoded><![CDATA[<p>
最近突然脑子一热，Read It Later好、Instapaper也好，保存的网页都是在别人的服务器上，使用别人的工具来浏览，总感觉受牵制，干脆自己倒腾一个这样的工具，把数据提交到自己的网站空间里，之后使用Ipod Touch来看，这个更有保障，功能其实也就需要一个保存网页的URL并且在空闲的时候浏览，简单的一个收藏夹。并且可以顺便尝试使用Youtube的UIX事件机制。
</p>
<p><span id="more-1459"></span></p>
<p>
下面是简单的一个UIX事件绑定方式：
</p>
<p>[javascript]<br />
// UIX system<br />
var UIX = UIX || {<br />
  &quot;registry&quot;:{},<br />
  &quot;register&quot;:function(type,uixes){<br />
    if(!this.registry[type]){<br />
	  this.registry[type]={};<br />
	}<br />
	for(var uix in uixes){<br />
	  if(uixes.hasOwnProperty(uix)){<br />
	    this.registry[type][uix] = uixes[uix];<br />
	  }<br />
	}<br />
  },<br />
  &quot;handleEvent&quot;: function(evt){<br />
    if(evt.type in this.registry){<br />
	  var actions = this.registry[evt.type];<br />
	  for(var uix in actions){<br />
	    el = evt.target || evt.srcElement;<br />
        if(el.getAttribute(&quot;data-uix&quot;) == uix){<br />
	      actions[uix].call(el,evt);<br />
        }<br />
	  }<br />
	}<br />
  }<br />
};<br />
//End uix system<br />
[/javascript]</p>
<p>
如上代码所示，原理是将事件都绑定到document上，目标元素就使用自定义字段data-uix作为一类相似事件行为的标识，但是涉及到document以及具体的DOM元素的事件处理逻辑，所以就需要进行两个事件绑定的过程：第一个是将uix的事件接口绑定到document上，之后声明每一类的自定义data-uix事件处理程序，这个并不是绑定的方式，而是以data-uix为标识的映射函数
</p>
<p>[javascript]<br />
// UIX system 派上用场了<br />
//document绑定事件<br />
addEvent(document,&quot;click&quot;,function(e){<br />
  UIX.handleEvent(e || window.event);<br />
});<br />
UIX.register(&quot;click&quot;,{<br />
  &quot;mask_read&quot;:function(){  //data-uix为mask_read的一类click事件。<br />
    var index = this.getAttribute(&quot;data-index&quot;);<br />
    var url = this.getAttribute(&quot;data-href&quot;);<br />
    location.href = &quot;mask_read.php?index=&quot;+index+&quot;&amp;url=&quot; + encodeURIComponent(url);<br />
	return true;<br />
  },<br />
  &quot;read_button&quot;:function(){ //data-uix为read_button的一类click事件。<br />
    getData.request(this.getAttribute(&quot;data-read&quot;));<br />
  }<br />
});<br />
[/javascript]</p>
<p>
使用这样的微UIX事件绑定机制，可以根据事件类型来区分该事件类型下的每一类绑定该事件的元素集合，并且使用委托的方式。
</p>
<p>
UIX介绍完了，现在接下来说一下在Ipod Safari下开发这个所遇到的一些问题。首先说一下功能需求：提供已经阅读和未阅读的类型，那么区别这个已读跟未读的状态；页面需要基于Ajax请求，来加载URL列表。就这两个需求。
</p>
<ul>
<li>
在区别已读跟未读状态的时候，既要不阻碍点击URL的title进入到收藏的网址的网站，而且又能够在自己的数据库里标记这条URL已经阅读过，那么就需要在click事件的时候，发送一个请求给服务端，更新数据库的标识。通常的这个做法都是通过动态的New一个Image实例，声明src的方式，但是使用这个方式的时候，FF浏览器下好使，但是Chrome、Safari、Ipod Safari不好使了，无效。因为src指向的是一个php的页面，有朋友测试妨碍西安src如果不指向一个图片的时候，请求无效。所以这种方式使用Image实例指向php页面的方式就不行了（之后测试了使用script标签指向php文件的方式，也不行）。只有使用比较搓的备选方案了，使用中间跳转页的方式，但是这样又会遇到这个样的一个问题：浏览器回退的时候会跳到这个中间页，如果才能够把这个中间页不在浏览器的history里保存呢？方案是有的，使用location.replace做跳转，replace接受一个url的字符串参数，表示跳转到该url下，而不把当前URL记录到history中。
</li>
<li>
第二个需求中，又会遇到怎样的问题呢？异步请求的更新问题，问题还是纠结在浏览器回退的时候，网址夹页面中已经点击过的URL应该清除掉，因为它已经阅读过了。FF、Chrome浏览器下点击回退按钮的时候，会自动重新发送Ajax请求去加载数据，而Safari、Opera、Ipod Safari却没有，那么这就又纳闷了。经过跟朋友讨论过之后，使用：window.onunload=window.onbeforeunload=function(){};<br />
就好使了，Safari、Opera、Ipod Safari都会自动重新发送请求，更新页面。大致的意思就是声明了这个onunload、onbeforeunload之后，浏览器不会cache页面的内容。
</li>
</ul>
<p>
本来以为做这个会很简单，Ipod Safari下总会遇到各种各样跟浏览器不同的行为，特别在事件方面，支持的程度不同之外，触发、执行的方式都有可能不同，或者因为其他的影响而有莫名其妙的失效的情况。
</p>
<p>
由于个人网址夹是open、并且是个人使用的，所以就不在此提供测试地址了。YY一下</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ilovejs.net/archives/1459/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Perl编译程序升级build-1.1.1</title>
		<link>http://www.ilovejs.net/archives/1457</link>
		<comments>http://www.ilovejs.net/archives/1457#comments</comments>
		<pubDate>Sun, 16 Jan 2011 08:24:54 +0000</pubDate>
		<dc:creator>Supersha</dc:creator>
				<category><![CDATA[开发工具]]></category>
		<category><![CDATA[Perl Build]]></category>
		<category><![CDATA[工具]]></category>

		<guid isPermaLink="false">http://www.ilovejs.net/?p=1457</guid>
		<description><![CDATA[2011-1-17 updates: 今天在给组内介绍这个东东的时候，有提出是否使用这个工具后的开发方式，是否会依赖于这个工具进行开发。我想这要分两种情况： 如果在一个页面内开发的话，那么就可以使用行内压缩的方式，在标签里添加几个标记，而不会影响到页面的正常的标签。不使用该工具的话，完全可以将这些标识去掉。 如果是使用include的方式的话。那么既然使用了这种方式，那么就必然需要使用一个编译程序来编译你的include语法，这样对于使用什么工具开发，都会依赖于该工具。在这里只是使用了include的方式，并添加了一个压缩、语法检查，如果需要原始未压缩版的，那么完全可以使用不压缩的方式，编译出来之后就是完整的一个页面，毫无副作用。 当初就是为了能够使得页面内就可以进行压缩，才添加了c:和compress语法。当初的这样的做法，也是为了适应当前自己做的项目出发的。 详细说明图示 ============ updates分界线 ============= 在平时开发的过程中，一直都在使用这个工具来压缩、纠错等等，但是在不同的文件中可能是不同的，有些需要编译的文件可能是只对HTML标签进行压缩、或者对页面行内js、css进行压缩，如果都使用include的方式，可能就太局限了。因此，对编译程序又作出了修改。 此次修改点包括： 添加页面内标记有compress的script、style标签的压缩 对HTML标签使用c:标记的标签压缩 去掉了cscript.exe来执行js代码，进行纠错的功能 说明： 对行内js、css压缩的语法： [html] &#60;script compress &#8230; <a href="http://www.ilovejs.net/archives/1457" class="more-link">了解更多</a>]]></description>
			<content:encoded><![CDATA[<p>
<strong>2011-1-17 updates:</strong>
</p>
<p>
今天在给组内介绍这个东东的时候，有提出是否使用这个工具后的开发方式，是否会依赖于这个工具进行开发。我想这要分两种情况：
</p>
<ol>
<li>如果在一个页面内开发的话，那么就可以使用行内压缩的方式，在标签里添加几个标记，而不会影响到页面的正常的标签。不使用该工具的话，完全可以将这些标识去掉。</li>
<li>如果是使用include的方式的话。那么既然使用了这种方式，那么就必然需要使用一个编译程序来编译你的include语法，这样对于使用什么工具开发，都会依赖于该工具。在这里只是使用了include的方式，并添加了一个压缩、语法检查，如果需要原始未压缩版的，那么完全可以使用不压缩的方式，编译出来之后就是完整的一个页面，毫无副作用。</li>
</ol>
<p>
当初就是为了能够使得页面内就可以进行压缩，才添加了c:和compress语法。当初的这样的做法，也是为了适应当前自己做的项目出发的。
</p>
<p>
<a  href="/images/per_build.jpg" rel="wp-prettyPhoto[g1457]">详细说明图示</a>
</p>
<p>
============ updates分界线 =============
</p>
<p>
在平时开发的过程中，一直都在使用这个工具来压缩、纠错等等，但是在不同的文件中可能是不同的，有些需要编译的文件可能是只对HTML标签进行压缩、或者对页面行内js、css进行压缩，如果都使用include的方式，可能就太局限了。因此，对编译程序又作出了修改。
</p>
<p>
此次修改点包括：
</p>
<ul>
<li>添加页面内标记有compress的script、style标签的压缩</li>
<li>对HTML标签使用c:标记的标签压缩</li>
<li>去掉了cscript.exe来执行js代码，进行纠错的功能</li>
</ul>
<p>
<strong>说明：</strong>
</p>
<p>
对行内js、css压缩的语法：
</p>
<p>[html]<br />
&lt;script compress id=&quot;test&quot;&gt;&#8230;&lt;/script&gt;<br />
&lt;style compress&gt;&#8230;&lt;/style&gt;<br />
[/html]</p>
<p>
对HTML进行压缩的语法（要配对的使用c:进行开始和结束标签的标记）：
</p>
<p>[html]<br />
&lt;c:head&gt;<br />
&lt;meta charset=&#8217;utf-8&#8242;&gt;<br />
&lt;title&gt;Template&lt;/title&gt;<br />
&lt;/c:head&gt;<br />
[/html]</p>
<p>
之前本来打算对script、css、html标签进行相同的c:标记处理，但是script、css进行这样标记之后，在一些编辑器（Editplus等）中，代码高亮、自动完成功能都会失效，所以还是使用独立的compress的属性方式了。
</p>
<p>最新编译程序下载：<a  href="/download/build-1-1-1.rar">build-1-1-1.rar</a></p>
<p>
具体的安装和使用方式，请浏览：<a  href="http://www.ilovejs.net/archives/1407">Perl build程序升级build-1-0-8</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.ilovejs.net/archives/1457/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>名站分析之eBay</title>
		<link>http://www.ilovejs.net/archives/1455</link>
		<comments>http://www.ilovejs.net/archives/1455#comments</comments>
		<pubDate>Fri, 14 Jan 2011 02:43:59 +0000</pubDate>
		<dc:creator>Supersha</dc:creator>
				<category><![CDATA[名站分析]]></category>
		<category><![CDATA[eBay]]></category>
		<category><![CDATA[分析]]></category>

		<guid isPermaLink="false">http://www.ilovejs.net/?p=1455</guid>
		<description><![CDATA[eBay(http://www.ebay.com/) 整个页面都进行了压缩，不管是行内js、css还是外联的，以及HTML代码，都压缩了，这点做的比较到位，而且不能是纯手工来做的。这点符合我最近的想法，使用工具来完成这个事情，那么在提交给QA测试的时候，页面就必须是全面压缩过的，勇于试错，踩的坑多了才能避免后面的人踩的坑更少。 看到很多网站都有这样的link元素声明： &#60;link rel=”canonical” href=”http://www.ebay.com”&#62; 查阅之后，才知道又是为了SEO上的优化，避免搜索引擎重复收录同样的页面。 http://www.fqyy8.com/archives/3045.html Body标签内中的style、script行内样式、脚本比较多，而且外联的几个js文件也夹杂在其中，所以从HTTP瀑布图来看，造成了阻塞，好在FF在js的加载方面提升了，能够跟其他的资源并行加载。 当然这样做的目的很多，有一个目的叫做“让功能尽早可用，当功能不可用的时候，让关键的功能稳步退化可用”，那么从这个角度来考虑，在head加载js、或者在body内加行内js，就情有可原了，让js紧随HTML结构的后面，可以使得脚本尽快的执行，但是要注意在IE6下的终止错误，将js行内脚本跟需要处理的HTML标签的父元素并行。 对于页面初始化的js，放到head标签内比较合理，维护方便。 由于页面meta、link、charset、doctype等声明在各个网站中都有所不同，所以需要整理出来哪些是必须的（SEO、性能优化、浏览器兼容doctype等），并且通过一个工具来检查，后期打算做这样的一个工具，集成到firebug中，方便使用。比如，eBay的首页页面源码中出现了两个meta charset声明。 页面头部使用了三个css文件，并且标记了版本控制，这样的方式，使用Combo的方式很不错的选择。 不得不说，ebay的js的命名空间，不是一般的长：vjo.dsf.error.ErrorHandlerManager.enableOnError 如果没有一个健全的API文档、或者使用IDE进行自动提示，那么在编写的时候很容易出错，也不方便代码的编写。这些命名空间都是通过vjo.ctype创建出来的，并且链式使用protos附加构造函数，并且还有一个needs的函数用于标记该命名空间需要其他的命名空间的支持。用vjo.ctype创建出来的，缈似一个个模块，之后在页面中直接调用。]]></description>
			<content:encoded><![CDATA[<p>
<span style="font-family:微软雅黑;font-size:18px;color:#f0f;">eBay(<a href="http://www.ebay.com/">http://www.ebay.com/</a>)</span>
</p>
<ul>
<li>整个页面都进行了压缩，不管是行内js、css还是外联的，以及HTML代码，都压缩了，这点做的比较到位，而且不能是纯手工来做的。这点符合我最近的想法，使用工具来完成这个事情，那么在提交给QA测试的时候，页面就必须是全面压缩过的，勇于试错，踩的坑多了才能避免后面的人踩的坑更少。</li>
<li>看到很多网站都有这样的link元素声明：<br />
&lt;link rel=”canonical” href=”http://www.ebay.com”&gt;<br />
查阅之后，才知道又是为了SEO上的优化，避免搜索引擎重复收录同样的页面。<br />
<a  href="http://www.fqyy8.com/archives/3045.html">http://www.fqyy8.com/archives/3045.html</a>
</li>
<li>Body标签内中的style、script行内样式、脚本比较多，而且外联的几个js文件也夹杂在其中，所以从HTTP瀑布图来看，造成了阻塞，好在FF在js的加载方面提升了，能够跟其他的资源并行加载。<br />
当然这样做的目的很多，有一个目的叫做“让功能尽早可用，当功能不可用的时候，让关键的功能稳步退化可用”，那么从这个角度来考虑，在head加载js、或者在body内加行内js，就情有可原了，让js紧随HTML结构的后面，可以使得脚本尽快的执行，但是要注意在IE6下的终止错误，将js行内脚本跟需要处理的HTML标签的父元素并行。<br />
对于页面初始化的js，放到head标签内比较合理，维护方便。
</li>
<li>由于页面meta、link、charset、doctype等声明在各个网站中都有所不同，所以需要整理出来哪些是必须的（SEO、性能优化、浏览器兼容doctype等），并且通过一个工具来检查，后期打算做这样的一个工具，集成到firebug中，方便使用。比如，eBay的首页页面源码中出现了两个meta charset声明。</li>
<li>页面头部使用了三个css文件，并且标记了版本控制，这样的方式，使用Combo的方式很不错的选择。</li>
<li>不得不说，ebay的js的命名空间，不是一般的长：vjo.dsf.error.ErrorHandlerManager.enableOnError<br />
如果没有一个健全的API文档、或者使用IDE进行自动提示，那么在编写的时候很容易出错，也不方便代码的编写。这些命名空间都是通过vjo.ctype创建出来的，并且链式使用protos附加构造函数，并且还有一个needs的函数用于标记该命名空间需要其他的命名空间的支持。用vjo.ctype创建出来的，缈似一个个模块，之后在页面中直接调用。
</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.ilovejs.net/archives/1455/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>名站分析之YouTube</title>
		<link>http://www.ilovejs.net/archives/1447</link>
		<comments>http://www.ilovejs.net/archives/1447#comments</comments>
		<pubDate>Thu, 13 Jan 2011 10:37:41 +0000</pubDate>
		<dc:creator>Supersha</dc:creator>
				<category><![CDATA[名站分析]]></category>
		<category><![CDATA[youtube]]></category>
		<category><![CDATA[分析]]></category>

		<guid isPermaLink="false">http://www.ilovejs.net/?p=1447</guid>
		<description><![CDATA[YouTube(http://www.youtube.com/) 页面使用了HTML5的doctype，可是却没有见到charset的声明，整个head都没有，而是直接来了一几段js代码。但是在开头看到这样的一段代码用于统计时间信息的： [javascript] try { yt.timing['srt'] = window.gtbExternal &#38;&#38; window.gtbExternal.pageT() &#124;&#124; window.external &#38;&#38; window.external.pageT; } catch(e) { } if (window.chrome &#8230; <a href="http://www.ilovejs.net/archives/1447" class="more-link">了解更多</a>]]></description>
			<content:encoded><![CDATA[<p>
<span style="font-family:微软雅黑;font-size:18px;color:#f0f;">YouTube(<a href="http://www.youtube.com/">http://www.youtube.com/</a>)</span>
</p>
<ul>
<li>
页面使用了HTML5的doctype，可是却没有见到charset的声明，整个head都没有，而是直接来了一几段js代码。但是在开头看到这样的一段代码用于统计时间信息的：<br />
[javascript]<br />
    try {<br />
      yt.timing['srt'] = window.gtbExternal &amp;&amp; window.gtbExternal.pageT() ||<br />
     window.external &amp;&amp; window.external.pageT;<br />
 } catch(e) {<br />
}<br />
    if (window.chrome &amp;&amp; window.chrome.csi) {<br />
      yt.timing['srt'] = Math.floor(window.chrome.csi().pageT);<br />
    }<br />
    if (window.msPerformance &amp;&amp; window.msPerformance.timing) {<br />
      yt.timing['srt'] = window.msPerformance.timing.responseStart &#8211; window.msPerformance.timing.navigationStart;<br />
}<br />
[/javascript]<br />
这里用到了Chrome浏览器独有的chrome对象扩展，同时，也使用了IE9中msPerformance对象的扩展属性，用于收集一些助于分析性能的信息，之前就看过IE9有这玩意，在这里看到使用场景了，YouTube还真不赖，创新不断，看来还真是“创新是需要勇气”滴。<br />
<a  href="http://ecmanaut.blogspot.com/2010/06/google-bom-feature-ms-since-pageload.html">http://ecmanaut.blogspot.com/2010/06/google-bom-feature-ms-since-pageload.html</a> <br />
这样做的目的，可能是使得在页面刚开始加载的时候就统计时间信息，减少误差。
</li>
<li>使用img在页面解析的时候首先进行DNS Lookup：<br />
[javascript]<br />
    yt.preload.start = function() {<br />
      var img = new Image();<br />
      yt.preload.videoConnection = img;<br />
      img.onload = img.onerror = function () {<br />
        delete yt.preload.videoConnection;<br />
      };<br />
      img.src =<br />
&#8216;http:\/\/v5.lscache2.c.youtube.com\/generate_204?sparams=id%2Cexpire%2Cip%2Cipbits%2C<br />
itag%2Calgorithm%2Cburst%2Cfactor%2Coc%3AU0dYSVlLU19FSkNNOF9RRVdH&amp;fexp=910102&amp;algorith<br />
m=throttle-factor&amp;itag=34&amp;ipbits=0&amp;burst=40&amp;sver=3&amp;signature=A1791B339659467A5233C71BD<br />
394ECC299548EBE.88354CA11413C832E67AA3411C7D119E7F024521&amp;expire=1294905600&amp;key=yt1&amp;ip=<br />
0.0.0.0&amp;factor=1.25&amp;id=d689799c76e71c93&#8242;;<br />
      img = null;<br />
    };<br />
yt.preload.start();<br />
[/javascript]<br />
这样做的目的在于，为接下来的视频的加载提前进行了DNS Lookup，减少视频加载的时间。在视频详情页是看不到这个img提前进行DNS Lookup脚本的，因为已经没必要了，进行了配置。<br />
或者可以利用这个时间信息进行判断，进行用户体验上的稳步退化、或者进行额外的加载策略。。。
</li>
<li>对于页头logo的设计上，使用了一个1*1像素的透明图片，然后对它进行定宽高，并且添加背景。刚开始看这个还不明所以，看过那个大sprites之后，突然恍然大悟。为啥人家的sprites可以拼凑的那么密密麻麻，而且还互相不受影响，原来都是定宽高了。<br />
对于为啥使用图片的方式，那是因为YouTube基本整站的背景修饰样式，都是使用1*1的透明图片、定宽高、应用背景的方式，整个页面使用一个图片。<br />
图片的URL忽略了host：//s.ytimg.com/yt/img/pixel-vfl3z5WfW.gif，这样在http、https下浏览页面都没问题。不过需要注意的是，使用这种方式应用在CSS文件上，在IE下会download两次。<br />
使用图片的方式，对于应用背景就更加的独立，扩展好，提高复用度，在CSS的编写上就更加的少了。 <br />
但是这种方式，也有缺点：</p>
<ol>
<li>对图片进行缩放，在页面渲染上至少会花费更多的性能，对于大宽高的话，性能消耗会很明显。</li>
<li>必须对图片进行宽高的限定，否则会露馅，因此适用的范围会比较小。</li>
</ol>
</li>
<li>在底部页码的实现中，使用了button的方式，而不使用超链接，估计是从统一页面样式上的考虑吧，页码看起来更像是一个个按钮。在每一个按钮上处理window.location.href为该button的href属性值。使用window.location.href来导航会导致这样的一个问题：目标页中在IE下document.referrer会丢失。不管是使用localtion.href、window.open、提交表单等方式，都会导致document.referrer丢失。<br />
<a  href="http://www.imkevinyang.com/2010/01/document-referrer%E4%B8%A2%E5%A4%B1%E7%9A%84%E5%87%A0%E4%B8%AA%E5%8E%9F%E5%9B%A0.html">http://www.imkevinyang.com/2010/01/document-referrer%E4%B8%A2%E5%A4%B1%E7%9A%84%E5%87%A0%E4%B8%AA%E5%8E%9F%E5%9B%A0.html</a>
</li>
<li>在js代码中，看到最多的莫过于yt.setConfig、yt.pubsub.subscribe，这个整体看起来页面就想通过配置拼装起来的一样，对于每一个模块，使用配置来使得模块根据显示声明的方式来工作。通过查看这个js文件：<br />
s.ytimg.com/yt/jsbin/www-core-vflv-060B.js<br />
Youtube的这个js库封装了window下的一些方法，基于yt的命名空间，这种调用方式很新颖。
</li>
<li>之前看过YouTube的开发人员介绍过UIX widget system。在一些button按钮上已经看到有uix的命名空间了。现在来简要的说一下这个UIX，它是利用事件冒泡的机制，将需要的事件类型都绑定到document上，之后每一个button触发各种类型冒泡到document上，并执行相应的事件逻辑程序。<br />
UIX system在register的时候，需要使用一个class进行标识，并提供相应的事件类型、处理函数。所以这里就有两层的事件绑定，一个是document，一个是具体的事件源DOM元素。使用class的方式一个是从“物以类聚”的性质来考虑，可以在多个按钮上使用系统的class，一个是达到了样式通用，另一个是事件标识通用。<br />
但是这样会不足够的灵活，事件逻辑跟样式耦合在一起，而且在维护上会有一定的风险，万一class给改掉，那就over了。<br />
所以，我比较倾向于使用自定义字段的方式，使用自定义的话，这个就将UIX完全的独立出来了，而且也可以通过给自定义字段设置相同的属性值来达到“物以类聚”的功能。简单的示例如下：<br />
[html]<br />
&lt;button id=&quot;btn1&quot; data-uix=&quot;btn_uix_click1&quot;&gt;猛击吧1&lt;/button&gt;<br />
&lt;button id=&quot;btn2&quot; data-uix=&quot;btn_uix_click2&quot;&gt;猛击吧2&lt;/button&gt;<br />
&lt;button id=&quot;btn3&quot; data-uix=&quot;btn_uix_click3&quot;&gt;猛击吧3&lt;/button&gt;<br />
[/html]<br />
[javascript]<br />
var addEvent = function(e,t,f){<br />
  (addEvent = e.attachEvent ? function(e,t,f){<br />
    e.attachEvent(&quot;on&quot;+t,function(){f.call(e);});<br />
  }: function(e,t,f){<br />
    e.addEventListener(t,f,false);<br />
  })(e,t,f);<br />
}</p>
<p>//UIX control<br />
var UIX = UIX || {<br />
  &quot;registry&quot;:{},<br />
  &quot;register&quot;:function(type,uixes){<br />
    if(!this.registry[type]){<br />
	  this.registry[type]={};<br />
	}<br />
	for(var uix in uixes){<br />
	  if(uixes.hasOwnProperty(uix)){<br />
	    this.registry[type][uix] = uixes[uix];<br />
	  }<br />
	}<br />
  },<br />
  &quot;handleEvent&quot;: function(evt){<br />
    if(evt.type in this.registry){<br />
	  var actions = this.registry[evt.type];<br />
	  for(var uix in actions){<br />
	    el = evt.target || evt.srcElement;<br />
        if(el.getAttribute(&quot;data-uix&quot;) == uix){<br />
	      actions[uix].call(el,evt);<br />
        }<br />
	  }<br />
	}<br />
  }<br />
};</p>
<p>UIX.register(&quot;click&quot;,{<br />
  &quot;btn_uix_click1&quot;:function(){alert(&quot;btn_uix_click1&quot;);},<br />
  &quot;btn_uix_click2&quot;:function(){alert(&quot;btn_uix_click2&quot;);},<br />
  &quot;btn_uix_click3&quot;:function(){alert(&quot;btn_uix_click3&quot;);}<br />
});</p>
<p>addEvent(document,&quot;click&quot;,function(e){<br />
  UIX.handleEvent(e || window.event);<br />
});<br />
[/javascript]
</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.ilovejs.net/archives/1447/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>系统开发工具整理备份</title>
		<link>http://www.ilovejs.net/archives/1438</link>
		<comments>http://www.ilovejs.net/archives/1438#comments</comments>
		<pubDate>Wed, 12 Jan 2011 06:59:25 +0000</pubDate>
		<dc:creator>Supersha</dc:creator>
				<category><![CDATA[开发工具]]></category>
		<category><![CDATA[前端环境]]></category>
		<category><![CDATA[工具]]></category>

		<guid isPermaLink="false">http://www.ilovejs.net/?p=1438</guid>
		<description><![CDATA[最近一直在总结自己的东西，整理了一下自己在前端开发过程中使用的比较多、使用起来比较顺手、开发效率快、适合自己开发习惯的一些工具，同时还有一些辅助的工具：移动设备、虚拟机等，这些在管理自己的时间、项目、计划方面都非常的实用。但是最重要的一点是：重装系统之后，我就可以按照这个工具表来搭建自己的开发环境，着手开发。 使用顺手，提高自己编程乐趣以及开发效率的工具，应该整理成自己的东西。我的收藏单，在此备一份（会逐步更新）： 开发软件： xmind：思维导图软件 Editplus: 添加自动完成功能；通过手写的方式，可以尽快的熟悉HTML的各个标签、CSS各个样式规则的命名拼写、JS各个对象和方法属性的拼写；添加更多的用户工具。 HTML5：准备一份HTML5的html模板文件，用于在Editplus下默认的新建html的文档模板。 IE：装一个最新的IE版本、其他的版本在虚拟机下安装 Ubuntu：在虚拟机下安装一个吧，尝试Linux下的编码生活 给ubuntu下的命令行添加sudo apt-get install cgvg，cgvg工具，用于查找当前目录下的grep文件的功能。 Bluefish:ubuntu下的一个IDE。 HTTPWatch：IE下强大的查看HTTP瀑布图、HTTP头文件的利器 Fiddler：抓任何的HTTP包、调试工具 Chrome:read it later插件 Safari &#8230; <a href="http://www.ilovejs.net/archives/1438" class="more-link">了解更多</a>]]></description>
			<content:encoded><![CDATA[<p>
最近一直在总结自己的东西，整理了一下自己在前端开发过程中使用的比较多、使用起来比较顺手、开发效率快、适合自己开发习惯的一些工具，同时还有一些辅助的工具：移动设备、虚拟机等，这些在管理自己的时间、项目、计划方面都非常的实用。但是最重要的一点是：重装系统之后，我就可以按照这个工具表来搭建自己的开发环境，着手开发。
</p>
<p><span id="more-1438"></span></p>
<p>
使用顺手，提高自己编程乐趣以及开发效率的工具，应该整理成自己的东西。我的收藏单，在此备一份（会逐步更新）：
</p>
<p>
<strong>开发软件：</strong>
</p>
<ul>
<li>xmind：思维导图软件</li>
<li>Editplus: 添加自动完成功能；通过手写的方式，可以尽快的熟悉HTML的各个标签、CSS各个样式规则的命名拼写、JS各个对象和方法属性的拼写；添加更多的用户工具。</li>
<li>HTML5：准备一份HTML5的html模板文件，用于在Editplus下默认的新建html的文档模板。</li>
<li>IE：装一个最新的IE版本、其他的版本在虚拟机下安装</li>
<li>Ubuntu：在虚拟机下安装一个吧，尝试Linux下的编码生活</li>
<li>给ubuntu下的命令行添加sudo apt-get install cgvg，cgvg工具，用于查找当前目录下的grep文件的功能。</li>
<li>Bluefish:ubuntu下的一个IDE。</li>
<li>HTTPWatch：IE下强大的查看HTTP瀑布图、HTTP头文件的利器</li>
<li>Fiddler：抓任何的HTTP包、调试工具</li>
<li>Chrome:read it later插件</li>
<li>Safari</li>
<li>Opera：第一次加载好Opera下的调试工具，第一次需要联网下载</li>
<li>Firefox：firebug、yslow、page speed、Read it later</li>
<li>SVN：版本管理，代码备份，协同开发</li>
<li>Photoshop：切图的必备工具</li>
<li>SUN Virtual Box:虚拟机</li>
<li>Dropbox：资源共享，类似于SVN，缺点就是依赖于dropbox平台，而且免费的空间较小。</li>
<li>JSLint:给Editplus或者vim、NotePad++配置上JSLint语法检查。(http://www.vfresh.org/js/980)</li>
<li>Zen Coding:给Editplus或者NotePad++配置上Zen Coding。（http://www.vfresh.org/w3c/914）</li>
<li>YUI Compressor：给Editplus添加上这个压缩js、css的工具。(http://hi.baidu.com/vivaid/blog/item/68fe35736c1d440d8701b08b.html)</li>
<li>给Editplus添加上Perl Build（自己开发的工具，可以将这个Build.pl放到任何的目录下，在Editplus的Argument写明绝对地址即可）</li>
</ul>
<p>
<strong>辅助工具：</strong>
</p>
<ul>
<li>Google Reader：学习之用，也是分享的一个平台</li>
<li>Adobe Reader：pdf文件阅读器</li>
<li>Office2007一件套</li>
<li>VPN:用于查看长城外面的技术、牛人</li>
<li>Twitter：关注领域内的牛人的动态</li>
<li>Executor：快速的快捷键方式</li>
<li>Filezilla：FTP工具</li>
<li>iFunBox：跟ipod传输数据工具</li>
</ul>
<p>
<strong>Ipod Touch软件（没钱，都是破解版或者免费的）：</strong>
</p>
<ul>
<li>Read it later：网页收藏夹</li>
<li>Ibooks：非常流畅的PDF、PPT阅读器</li>
<li>PDF Expert：阅读器</li>
<li>乐顺备忘录：日常安排任务管理</li>
<li>CHMate：chm文件阅读器</li>
<li>FeeddleRSS：搬Googld reader的数据在这个应用里</li>
<li>MobileRSS：跟Read it later非常好的结合</li>
<li>CodeViewer:查看js、html、css等文件。</li>
<li>Remember The Milk:任务管理软件</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.ilovejs.net/archives/1438/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>名站分析之Goo</title>
		<link>http://www.ilovejs.net/archives/1435</link>
		<comments>http://www.ilovejs.net/archives/1435#comments</comments>
		<pubDate>Wed, 12 Jan 2011 02:10:07 +0000</pubDate>
		<dc:creator>Supersha</dc:creator>
				<category><![CDATA[名站分析]]></category>
		<category><![CDATA[Goo]]></category>
		<category><![CDATA[分析]]></category>

		<guid isPermaLink="false">http://www.ilovejs.net/?p=1435</guid>
		<description><![CDATA[Goo(http://www.goo.ne.jp/) Goo是日本的综合门户和搜索引擎, 隶属于日本最大电信公司NTT 通过查看HTTP瀑布图，在对不同性质的资源进行不同的域名管理方面，不甚合理。CSS、JS、Image等资源很多都还部署在主域goo.ne.jp下，而且在页面的很多修饰图片方面也比较零散，很多没有使用sprites的方式，导致过多的HTTP请求。 页面对js、css的优化似乎都做了处理，css在top、js在bottom，在HTML内容中穿插了一个加载广告用的document.write。这个好坏就不说了，这个document.write所加载的js还是一个动态的页面，还要依赖于该页面进行进一步的跳转来读取js文件，如果只是为了传递参数、在广告 (ad.nttnavi.co.jp)那边的服务器做判断的话，那么直接在js文件后面添加参数即可，而又何必使用这样的一个中间页面来做跳转呢（经过测试，使用这样的一个中间页读取另外的内容，之后将内容发送会客户端，所花费的时间比普通的直连文件的方式都要长，不管是将几个请求文件压缩为一个，最后返回。具体的测试请查看http://www.ilovejs.net/archives/449）。如果在服务端无法监控到每一个请求，并对该请求的参数进行判断、转发的话，退而求其次，使用服务端语言的中间页面来做判断，也就有些道理了，简单有保障。 为了保证广告一定可以出来，还是用上了noscript标签来加载一个图片。 搜索框中的suggestion做的很不错，展示了二次内容的选择，sug的内容是从search.goo.ne.jp传过来的数据，整个suggestion功能所使用到的css、js、数据都是来自这个域下，请求数据使用的是jsonp的方式，而没有使用简单的document.domain的方式，在主域和子域之间跨域。这个就看search.goo.ne.jp和goo.ne.jp的关系了。 不过它的这种suggestion的方式，还是首见的，创意很好。展示了更多的suggestion，对于用户或许是更好的用户体验、更多的选择，对站点来说，或许还是一次很好的卖点。 不过在输入框中使用了这样的一个样式属性：ime-mode。这个属性也是第一次看到，具体的作用查阅文档之后还是不太明了。不过它造成了Firefox下的问题，在切换tab的时候，首次获得了焦点，当点击输入框的时候，失去焦点，再点击输入框无法获取焦点进行输入了，要过几秒钟哇，还是随机的。 在右栏下边的关于时间点的内容切换中，一来没有使用按需加载的方式（这个估计跟架构上相关了，看是否支持这种自由的拉取数据的方式）；二来是静态内容，不包含任何内容，在li标签中使用div标签又包含了一层，不妥哇，即使是后期可能会在其中包含链接、图片啥的，有没div对展示内容都不受影响的。 可能最受我关注的是，是它对页面点击统计的方式，因为最近我也是一直在忙于点击统计的设计和重构，所以当看到goo的时候，发现了它进行了点击统计，所以分析了一番。 Goo基本对页面的每一个超链接都进行了统计，因为它对输出的每一个超链接设置了一个唯一的id，这个唯一的id，这个唯一的id的格式是(\w)-(\w+)-(\d)。从页面结构分析，第一个是表示大的分块区域，中间的是这个块内的小块，第三个是链接的索引（在块内按照HTML结构的排序）。 刷新页面之后，内容变化了，但是这个唯一的id还是不变的。那么这么设置有这样的好处：用户点击了哪里、点击的是哪一小块、点击的是哪一条、点击之后到哪个页面、块之间的切换等这些信息，同时，还简化了点击的事件逻辑，减少点击日志的丢失率（如果事件逻辑太过复杂，那么在点击事件发生过于频繁的时候，会造成一定的执行延迟，之后用户再关闭浏览器，那日志就丢失了）。最主要的是在还原页面的点击信息方面方便简单，对信息进行归类，之后在后台显示点击次数、点击顺序图、热力图方面都比较方便。 而且这样在页面改版的时候，对这些分块的逻辑不变，那么后端的解析程序，还是可以完好的跑。前端的解析脚本也可以完好的跑。 缺点就是增加了页面的体积，增加了过多的id数量。 还有一点就是：发送这个日志的方式，却是使用动态创建一个iframe，并指定iframe的src来发送请求，怪哉！使用动态创建Image的方式不是简单直接的多么。 其他的使用delegate、在父元素上定义块级标识、动态去算每一个超链接的索引的方式，都增加了事件逻辑的复杂度。但是这种方式，可以一方面减少页面体积，另一方面是在多人合作的时候，可以完全不管这个点击统计的存在，只要父元素中标识好块信息，管里面怎么折腾。但是这算超链接的索引的，可就需要花费一些心思来考虑到大部分的情况了。]]></description>
			<content:encoded><![CDATA[<p>
<span style="font-family:微软雅黑;font-size:18px;color:#f0f;">Goo(<a href="http://www.goo.ne.jp/">http://www.goo.ne.jp/</a>)</span>
</p>
<p>
Goo是日本的综合门户和搜索引擎, 隶属于日本最大电信公司NTT
</p>
<ol>
<li>通过查看HTTP瀑布图，在对不同性质的资源进行不同的域名管理方面，不甚合理。CSS、JS、Image等资源很多都还部署在主域goo.ne.jp下，而且在页面的很多修饰图片方面也比较零散，很多没有使用sprites的方式，导致过多的HTTP请求。</li>
<li>页面对js、css的优化似乎都做了处理，css在top、js在bottom，在HTML内容中穿插了一个加载广告用的document.write。这个好坏就不说了，这个document.write所加载的js还是一个动态的页面，还要依赖于该页面进行进一步的跳转来读取js文件，如果只是为了传递参数、在广告 (ad.nttnavi.co.jp)那边的服务器做判断的话，那么直接在js文件后面添加参数即可，而又何必使用这样的一个中间页面来做跳转呢（经过测试，使用这样的一个中间页读取另外的内容，之后将内容发送会客户端，所花费的时间比普通的直连文件的方式都要长，不管是将几个请求文件压缩为一个，最后返回。具体的测试请查看<a  href="http://www.ilovejs.net/archives/449">http://www.ilovejs.net/archives/449</a>）。如果在服务端无法监控到每一个请求，并对该请求的参数进行判断、转发的话，退而求其次，使用服务端语言的中间页面来做判断，也就有些道理了，简单有保障。<br />
为了保证广告一定可以出来，还是用上了noscript标签来加载一个图片。
</li>
<li>搜索框中的suggestion做的很不错，展示了二次内容的选择，sug的内容是从search.goo.ne.jp传过来的数据，整个suggestion功能所使用到的css、js、数据都是来自这个域下，请求数据使用的是jsonp的方式，而没有使用简单的document.domain的方式，在主域和子域之间跨域。这个就看search.goo.ne.jp和goo.ne.jp的关系了。<br />
不过它的这种suggestion的方式，还是首见的，创意很好。展示了更多的suggestion，对于用户或许是更好的用户体验、更多的选择，对站点来说，或许还是一次很好的卖点。
</li>
<li>不过在输入框中使用了这样的一个样式属性：ime-mode。这个属性也是第一次看到，具体的作用查阅文档之后还是不太明了。不过它造成了Firefox下的问题，在切换tab的时候，首次获得了焦点，当点击输入框的时候，失去焦点，再点击输入框无法获取焦点进行输入了，要过几秒钟哇，还是随机的。</li>
<li>在右栏下边的关于时间点的内容切换中，一来没有使用按需加载的方式（这个估计跟架构上相关了，看是否支持这种自由的拉取数据的方式）；二来是静态内容，不包含任何内容，在li标签中使用div标签又包含了一层，不妥哇，即使是后期可能会在其中包含链接、图片啥的，有没div对展示内容都不受影响的。</li>
<li>可能最受我关注的是，是它对页面点击统计的方式，因为最近我也是一直在忙于点击统计的设计和重构，所以当看到goo的时候，发现了它进行了点击统计，所以分析了一番。<br />
Goo基本对页面的每一个超链接都进行了统计，因为它对输出的每一个超链接设置了一个唯一的id，这个唯一的id，这个唯一的id的格式是(\w)-(\w+)-(\d)。从页面结构分析，第一个是表示大的分块区域，中间的是这个块内的小块，第三个是链接的索引（在块内按照HTML结构的排序）。<br />
刷新页面之后，内容变化了，但是这个唯一的id还是不变的。那么这么设置有这样的好处：用户点击了哪里、点击的是哪一小块、点击的是哪一条、点击之后到哪个页面、块之间的切换等这些信息，同时，还简化了点击的事件逻辑，减少点击日志的丢失率（如果事件逻辑太过复杂，那么在点击事件发生过于频繁的时候，会造成一定的执行延迟，之后用户再关闭浏览器，那日志就丢失了）。最主要的是在还原页面的点击信息方面方便简单，对信息进行归类，之后在后台显示点击次数、点击顺序图、热力图方面都比较方便。<br />
而且这样在页面改版的时候，对这些分块的逻辑不变，那么后端的解析程序，还是可以完好的跑。前端的解析脚本也可以完好的跑。<br />
缺点就是增加了页面的体积，增加了过多的id数量。<br />
还有一点就是：发送这个日志的方式，却是使用动态创建一个iframe，并指定iframe的src来发送请求，怪哉！使用动态创建Image的方式不是简单直接的多么。<br />
其他的使用delegate、在父元素上定义块级标识、动态去算每一个超链接的索引的方式，都增加了事件逻辑的复杂度。但是这种方式，可以一方面减少页面体积，另一方面是在多人合作的时候，可以完全不管这个点击统计的存在，只要父元素中标识好块信息，管里面怎么折腾。但是这算超链接的索引的，可就需要花费一些心思来考虑到大部分的情况了。
</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://www.ilovejs.net/archives/1435/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>名站分析之Naver</title>
		<link>http://www.ilovejs.net/archives/1431</link>
		<comments>http://www.ilovejs.net/archives/1431#comments</comments>
		<pubDate>Mon, 10 Jan 2011 05:19:05 +0000</pubDate>
		<dc:creator>Supersha</dc:creator>
				<category><![CDATA[名站分析]]></category>
		<category><![CDATA[Naver]]></category>
		<category><![CDATA[分析]]></category>

		<guid isPermaLink="false">http://www.ilovejs.net/?p=1431</guid>
		<description><![CDATA[Naver(http://www.naver.com/) Naver被号称韩国最大的门户网站，同时也提供搜索服务，所以对它进行了一个简要的分析。 首先，从网站的定位是门户来说，可是整体页面可以看到的信息量确实寥寥无几，整体界面简洁大方，很多的信息都需要基于用户的鼠标的驱动去显示出来，或者是自动轮询的方式显示。这个从门户的角度来讲，根据国内门户网站的特点，差异不是一般的大，孰好孰坏，让用户来品论了。 在页面的head标签内看到了这样的两句meta声明： [html] &#60;meta http-equiv=&#34;Content-Script-Type&#34; content=&#34;text/javascript&#34; /&#62; &#60;meta http-equiv=&#34;Content-Style-Type&#34; content=&#34;text/css&#34; /&#62; [/html] 从字面上去理解，是声明页面中script、style标签的类型。查阅文档之后，这是W3C近来的规范，用于声明脚本、样式的类型。 http://www.cnblogs.com/jerryshi/archive/2008/10/14/1310611.html 页面头部一大段的js，主要是为了声明一个DLScript的全局对象，用于动态的加载js，粗略的看了一下这段代码，还是有点意思的，复制保存了一下，空闲查看。 这段代码完了之后，就动态加载了一个JEnclk.js文件，先不看这个js的作用，从HTML来看，body之后的很大段代码都没见到什么行内脚本的执行，就后面有一个newscast_top_json的json结构的字符串，缈似需要解析。那么在head标签内使用那么一大段js篇幅并动态加载一个js文件，之后为了解析这个json的需要，那么就有点杀鸡用牛刀了。 或许可以将这段js移到主要的HTML内容的后面，对那段news的json延迟一点进行解析，这样提前的是整体的页面渲染时间。 Img标签都至少带有alt、height、width属性，这个非常好。 &#8230; <a href="http://www.ilovejs.net/archives/1431" class="more-link">了解更多</a>]]></description>
			<content:encoded><![CDATA[<p>
<span style="font-family:微软雅黑;font-size:18px;color:#f0f;">Naver(<a href="http://www.naver.com/">http://www.naver.com/</a>)</span>
</p>
<p>
Naver被号称韩国最大的门户网站，同时也提供搜索服务，所以对它进行了一个简要的分析。
</p>
<ol>
<li>首先，从网站的定位是门户来说，可是整体页面可以看到的信息量确实寥寥无几，整体界面简洁大方，很多的信息都需要基于用户的鼠标的驱动去显示出来，或者是自动轮询的方式显示。这个从门户的角度来讲，根据国内门户网站的特点，差异不是一般的大，孰好孰坏，让用户来品论了。
</li>
<li>在页面的head标签内看到了这样的两句meta声明：<br />
[html]<br />
&lt;meta http-equiv=&quot;Content-Script-Type&quot; content=&quot;text/javascript&quot; /&gt;<br />
&lt;meta http-equiv=&quot;Content-Style-Type&quot; content=&quot;text/css&quot; /&gt;<br />
[/html]<br />
从字面上去理解，是声明页面中script、style标签的类型。查阅文档之后，这是W3C近来的规范，用于声明脚本、样式的类型。<br />
<a href="http://www.cnblogs.com/jerryshi/archive/2008/10/14/1310611.html">http://www.cnblogs.com/jerryshi/archive/2008/10/14/1310611.html</a>
</li>
<li>页面头部一大段的js，主要是为了声明一个DLScript的全局对象，用于动态的加载js，粗略的看了一下这段代码，还是有点意思的，复制保存了一下，空闲查看。<br />
这段代码完了之后，就动态加载了一个JEnclk.js文件，先不看这个js的作用，从HTML来看，body之后的很大段代码都没见到什么行内脚本的执行，就后面有一个newscast_top_json的json结构的字符串，缈似需要解析。那么在head标签内使用那么一大段js篇幅并动态加载一个js文件，之后为了解析这个json的需要，那么就有点杀鸡用牛刀了。 或许可以将这段js移到主要的HTML内容的后面，对那段news的json延迟一点进行解析，这样提前的是整体的页面渲染时间。
</li>
<li>Img标签都至少带有alt、height、width属性，这个非常好。</li>
<li>对于阻止超链接默认的行为，使用了这样的方式：<br />
[html]<br />
&lt;a href=&quot;#&quot; class=&quot;pre&quot; onclick=&quot;return false;&quot;&gt;<br />
[/html]<br />
以前看到很多其他的网站也都这么使用，有些想不明白，在处理事件的程序中，最后return false一下，就解决问题了，何必又需要一个onclick呢，或者设置href属性值为“###”的方式。如果设置onclick的这种方式是为了进一步确保能够尽可能的阻止默认行为，避免处理程序中的疏忽，那么这个考虑，还是有些可以说的过去。
</li>
<li>在页面底部看到了一大段的JS代码，基本上是使用json来传输数据，之后通过js来动态解析，渲染页面，使用这种方式来动态加载一些不是最主要的内容的时候，还是比较适合的。但是我想，这其中最主要的一个思想是：<strong>跟后端的数据逻辑分离、开发上的分离</strong>。<br />
只要跟后端约定好数据接口和json结构，那么前端就可以通过js来解析这些接口所提供的数据，而不用后端人员关心页面的结构，或者后端负责去拼装页面，后端只需负责按照约定的接口传数据过来即可。这个对于一些列表数据尤其有意义，通过js直接拉取数据、拼装数据。
</li>
<li>后面使用window.onload事件来动态加载几个js文件，这个是从并行加载几个js文件来考虑，并且执行顺序没有依赖。但是这个方式，似乎可以使用Combo的方式来实现，而且效果更好。还有一点，既然是最后面，那么使用直接的方式：async=true,defer=true来声明一下各个标签，也是可以的。</li>
<li>打开页面有点久了，突然还发现会自动刷新一下，这个功能还会提供，估计是为了定时更新页面的一些news信息。但是这点，可以使用局部刷新、定时器定时去服务器去数据的方式来做，但是这样做有一个缺点就是：如果没有明显的提示信息，用户可能感觉不到信息已经更新。所以，简单粗暴一线，直接刷新页面，来得更直接。</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://www.ilovejs.net/archives/1431/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>名站分析之Alibaba</title>
		<link>http://www.ilovejs.net/archives/1425</link>
		<comments>http://www.ilovejs.net/archives/1425#comments</comments>
		<pubDate>Sat, 08 Jan 2011 16:37:10 +0000</pubDate>
		<dc:creator>Supersha</dc:creator>
				<category><![CDATA[名站分析]]></category>
		<category><![CDATA[Alibaba]]></category>
		<category><![CDATA[分析]]></category>

		<guid isPermaLink="false">http://www.ilovejs.net/?p=1425</guid>
		<description><![CDATA[Alibaba(http://www.alibaba.com/) 在head标签内声明了base标签，指定了href属性。通过查看base文档，才知道：base标签为页面上的所有链接规定默认地址或默认目标。通常情况下，浏览器会从当前文档的 URL 中提取相应的元素来填写相对 URL 中的空白，受它所影响的标签有：a、img、href、script、form等一切有URL声明的标签中。base标签必须位于head标签内。 对它了解了之后，那么利用它来优化页面代码的体积，就可以派上用场了。对于页面中超链接很多的情况下，这些超链接如果都带上主域的话，所占页面的总体积也是比较大的，所以利用base的这个属性，可以在很多的程度上减少url的长度，以及target的声明。 不过这个在复杂的页面中，特别是域名过多的情况下，需要一个很好的系统进行控制，区分好每一个模块中哪些是第三方、哪些是主域、哪些是静态资源所在的域名。 在head标签内的看到了这样的几句js代码： [javascript] (function(){ var im = new Image(); im.src = &#34;http://i02.i.aliimg.com/images/eng/style/css_images/home_new/homeSpritesV6.gif&#34;; var &#8230; <a href="http://www.ilovejs.net/archives/1425" class="more-link">了解更多</a>]]></description>
			<content:encoded><![CDATA[<p>
<span style="font-family:微软雅黑;font-size:18px;color:#f0f;">Alibaba(<a href="http://www.alibaba.com/">http://www.alibaba.com/</a>)</span>
</p>
<ol>
<li>在head标签内声明了base标签，指定了href属性。通过查看base文档，才知道：base标签为页面上的所有链接规定默认地址或默认目标。通常情况下，浏览器会从当前文档的 URL 中提取相应的元素来填写相对 URL 中的空白，受它所影响的标签有：a、img、href、script、form等一切有URL声明的标签中。base标签必须位于head标签内。<br />
对它了解了之后，那么利用它来优化页面代码的体积，就可以派上用场了。对于页面中超链接很多的情况下，这些超链接如果都带上主域的话，所占页面的总体积也是比较大的，所以利用base的这个属性，可以在很多的程度上减少url的长度，以及target的声明。<br />
不过这个在复杂的页面中，特别是域名过多的情况下，需要一个很好的系统进行控制，区分好每一个模块中哪些是第三方、哪些是主域、哪些是静态资源所在的域名。
</li>
<li>在head标签内的看到了这样的几句js代码：<br />
[javascript]<br />
(function(){<br />
var im = new Image();<br />
im.src = &quot;http://i02.i.aliimg.com/images/eng/style/css_images/home_new/homeSpritesV6.gif&quot;;<br />
var im2 = new Image();<br />
im2.src = &quot;http://i02.i.aliimg.com/images/eng/style/css_images/home_new/homeGradientBG.gif&quot;;<br />
})();<br />
[/javascript]<br />
这段代码中所列的图片的地址在头部的home_new.css文件中已经有了，那么这里还写这个，处于何种目的呢？用于统计又不太像。<br />
Youtube使用这种方式，是为了尽早的让浏览器进行DNS的lookups，在之后该域下的请求都不会进行DNS的lookups，并保持这个连接为打开状态，后续的资源的请求就可以直接跟服务器进行交互，而无需重新连接等步骤。这是一种对资源加载的优化，特别是在该资源特别需要提前加载的时候。
</li>
<li>看到很多超链接中带有了rel=“nofollow”，经过查看文档后发现，使用这个属性主要是为了处理搜索引擎爬虫的事情，在超链接中使用了这个属性，那么厚道的搜索引擎就不会去爬这个链接所指向的页面。这个更多的是有关SEO方面的考虑。<br /><a  href="http://www.google.com/support/webmasters/bin/answer.py?hl=zh-CN&#038;answer=96569">http://www.google.com/support/webmasters/bin/answer.py?hl=zh-CN&#038;answer=96569</a></li>
<li>页面中使用了很多的try…catch语句，不管是超链接中的javascript伪链接，还是一些行内的事件声明。这个从代码安全的角度来想，确实做的非常好的习惯，提供了一种在代码执行有错误的时候提供另外一种稳步退化的行为。<br />
特别是在超链接中的事件，本来想要在执行外事件处理程序的时候，return false来阻止超链接的默认行为，可是因为中间脚本错误，导致这个return false失效，那么原来的目的就达不到了，这个时候就可以针对特殊的情况下会出现的错误进行try…catch，在catch中进行另一种处理。<br />
还有就是在我们所倡导的“模块化”设计中，对容错机制的处理尤其重要，特别是需要在页面加载的时候会初始化执行的脚本，这样脚本会直接的影响到后续的代码是否可以顺利执行。使用try…catche来防止一些特殊的浏览器、特殊的行为下导致的错误，还是比较好的处理方式。
</li>
<li>noscript标签内包含一个img图片的方式缈似很普遍咯。但是它的主要作用就仅仅是用于某种统计吗？</li>
<li>页面中也使用了监控scroll事件来延迟加载图片的功能，在图片中使用了image-src的自定义属性，刚开始看也猜到到是为了这个目的，但是从这个命名上，又不能够直接的明白，所以只能够查找源文件进行证实。语意化啊。为了标记这个图片是需要延迟加载的，还给父元素的div添加了lazyload的类。<br />
看来这个监控scroll事件来延迟加载图片的功能，在一个长页面中还是十分有必要的，而且是在能够直接用数据证明大部分用户会查看页面下部分的内容的时候。
</li>
<li>看页面源码中，没怎么看到很多的行内js脚本，只是head标签内的一段初始化脚本、以及一些写在标签上的行内脚本之外，其他的就是头尾的两个外联的js。开始我还以为页面的交互功能、特效不多，所以js脚本才会很少，但是页面也很多模块化的效果哇，查看那两个js外联的脚本才发现，原来处理页面功能的很多js代码都压缩在那里了，而且还是跟YAHOO库的代码压缩在一起。刚开始想这样是不是有些太搓了，怎么维护？如果只是维护这一个js文件的话，那么将会是越来越混乱。<br />
但是，从另外的一个角度来想：如果有这样的一套系统，会自动的将开发阶段的几个js文件合并为一个，压缩并发布，那么这种处理跟yui、淘宝、口碑等之类的Combo的方式就达到了一个相同的目的：最小化HTTP请求。只是在页面上看起来似乎不是那么直观而已。
</li>
<li>对于class属性的使用上有些不够到位。对于一些列表、或者一些相似模块的样式上，虽然可以使用class可以定义通用的样式，但是class不要过度的应用到最底层的子元素上，而是尽量往更高的父元素上绑定class，通过它来声明子元素的通用的样式，而对于子元素私有的样式，那么可以进一步的使用class或者id来声明样式。</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://www.ilovejs.net/archives/1425/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

