<?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>不管是IE，还是Firefox、Chrome、Opera、Safari，爱它们，等于爱自己</description>
	<lastBuildDate>Fri, 03 Sep 2010 19:15:15 +0000</lastBuildDate>
		<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>妙用字面量对象来设计代码</title>
		<link>http://www.ilovejs.net/archives/1177</link>
		<comments>/archives/1177#comments-div</comments>
		<pubDate>Fri, 03 Sep 2010 18:28:04 +0000</pubDate>
		<dc:creator>Supersha</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[javascript pattern]]></category>
		<category><![CDATA[字面量对象]]></category>

		<guid isPermaLink="false">http://www.ilovejs.net/?p=1177</guid>
		<description><![CDATA[
最近一直在学习一些巧妙的设计代码编写的技巧，比如：单例模式，模块模式，类模式，字面量模式等等。其中单例模式、模块模式的写法又可以根据不同的特点有几种不同的变体。哈哈，有点走题了，本文主要说的不是这些，而是怎样利用字面量对象来设计代码。


当初利用三元运算符来代替多个if的逻辑，使得代码看起来简单，虽然牺牲了一点代码可读性，但是代码看起来没有那么臃肿了。对于if逻辑多的时候，可以使用switch来代替众多的if&#8230;else if逻辑，但是对于每一个分支比较复杂或者是很类似的时候，看到switch&#8230;case一连串，也感觉不爽，那么就是用字面量对象来代替吧，就如我下面所写的那样：


var checkFn=function(operation){
  return {
	'=':function(e) { return (e.getAttribute(attr) == attrValue); },
        '~':function(e) { return (e.getAttribute(attr).match(new RegExp('\\b'+attrValue+'\\b'))); },
        '&#124;':function(e) { return (e.getAttribute(attr).match(new RegExp('^'+attrValue+'-?'))); },
        '^':function(e) { return (e.getAttribute(attr).indexOf(attrValue) == 0); },
    [...]]]></description>
		<wfw:commentRss>http://www.ilovejs.net/archives/1177/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>javascript coding patterns</title>
		<link>http://www.ilovejs.net/archives/1165</link>
		<comments>/archives/1165#comments-div</comments>
		<pubDate>Wed, 25 Aug 2010 06:49:59 +0000</pubDate>
		<dc:creator>Supersha</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[javascript pattern]]></category>

		<guid isPermaLink="false">http://www.ilovejs.net/?p=1165</guid>
		<description><![CDATA[JavaScript code的编写模式多种多样，那么接下来总结一下大概都有哪几种，看看你是否都使用到了这些模式和思维：


Separation of concerns
即是我们平时挂在嘴边的行为、样式、结构分离（Content-markup、Presentation-CSS、Behavior-JavaScript），这在代码的扩展性、可维护性、易迁移性方面都可以得到很大的提升


Literals，JSON，namespace
Literals指的是codding尽量字面量化，对象字面量、数组字面量、函数字面量、正则字面量等等，这些都比使用new来实例Object、Array、Function性能上更好，甚至也推荐使用变脸的形式来声明函数，避免直接使用function来声明一个函数。
JSON提供一种更简洁、更直观的数据传输，在大小和解析方面都胜于XML。
namespace是尽量将每一个APP封装在一个独立的命名空间下，避免跟其他的APP模块产生耦合，产生错误。“低耦合”是namespace的一个终极目标。


Self-executing functions
顾名思义，就是指自定义函数，它用的比较多的场合是在闭包中，提供给code一个纯净的上下文执行环境，而不会造成全局变量泛滥


Callbacks
回调函数，用过“鸡查询(jQuery)”的人都知道，在执行完一个函数之后，再调用回调函数进行下一步的操作，做到了“流畅的执行流”。


Borrowing methods
别看Borrowing这个单词是“借”的意思，感觉有点高深，其实就是利用了apply和call两个方法来借用其他类或者对象的方法来实现功能，比较多的场合是借用数组的一些方法，比如slice、join等等，比如：[].apply(arguments,[1,3])。这只是普通用的比较多的情况，但是它还可以用在这样的一个场合，类似于“继承”：我首先使用一个“基类”&#8212;即是一个包含通用的方法和属性的对象，之后其他的结构跟它类似的对象就可以通过apply或者call来“借用”这个“基类”的方法，说的可能有些枯燥，上点代码：

var Base={
   name:&#34;&#34;,
  &#34;getName&#34;:function(){
      return this.name;
   },
   &#34;setName&#34;:function(name){
       this.name=name;
   }
}
//有了上面这个“骨架”之后，接下来就可以“借用”了
//比如从服务器端获得了这样的一个JSON结构：
var json={
  &#34;test1&#34;:{ &#34;name&#34;:&#34;lilei&#34;,&#34;age&#34;:22},
  &#34;test2&#34;:{ &#34;name&#34;:&#34;Sam&#34;,&#34;age&#34;:30},
  &#34;test3&#34;:{ &#34;name&#34;:&#34;Susa&#34;,&#34;age&#34;:15}
}
//这样我们就可以这样来调用了:
alert(Base.getName.call(json.test1));
///////////////
////////这只是个简单的例子，实用性并不高，提供的是一种设计思路，在某种场合或许就可以利用它



Functions returning functions
在函数中再返回函数，这也是比较普通的了，为特定的场合所使用


Functions overwriting themselves
函数重写它自己，这点或许很多人都知道怎么回事，但是怎么去利用它，还比较模糊。它的一个非常适用的场合就是处理浏览器兼容性的判断，也就是所谓的“Lazy Definition”。它就是在第一次执行的时候就根据不同的条件进行判断，来重写自身函数，这样在第二次之后的调用中就可以直接调用，而无需再判断兼容性等等，比如：

var addEvent=function(el,type,fn){
  addEvent=el.addEventListener ? function(el,type,fn){
 [...]]]></description>
		<wfw:commentRss>http://www.ilovejs.net/archives/1165/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>更加DIY的selector查询DOM</title>
		<link>http://www.ilovejs.net/archives/1160</link>
		<comments>/archives/1160#comments-div</comments>
		<pubDate>Wed, 11 Aug 2010 09:27:14 +0000</pubDate>
		<dc:creator>Supersha</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[DOM查询]]></category>
		<category><![CDATA[query]]></category>
		<category><![CDATA[querySelectorAll]]></category>

		<guid isPermaLink="false">http://www.ilovejs.net/?p=1160</guid>
		<description><![CDATA[
在上一篇文章中（谈谈松散耦合、颗粒度）提到的将javascript库或者框架更加向开发人员开放，DIY功能，尽量保持核心代码的精简和稳定，只开放接口，让开发人员根据特定的需求去DIY功能，而不是内定一整套方法集，供开发人员去使用。对此我例举了我写的query2.js为例子，这里就特别拿它出来说说。


query2中查询方式也是从左到右，这个是比较普通也容易实现的方式，有人说从右到左进行查询的话，效率会比较高，查询的复杂度较低。我想这就要开具体的selector了，如果是这样的“.test p”，那么从右到左的话复杂度就更高一些了，可能还得递归到document.body节点查询父元素的className是否等于test。所以双方面都有利有弊。


但是从左到右的查询方式还有一个比较苦恼的问题，就是“去重”（这是昨天跟瓶子吃饭的时候他提及到的问题），比如：


&#60;div&#62;
  &#60;div&#62;
    &#60;p&#62;Hello world&#60;/p&#62;
  &#60;/div&#62;
&#60;/div&#62;


这时候如果使用“div p”来查询p标签元素的时候，如果不去重，就会导致使用getElementsByTagName查询到两个p元素，如果是在查询结果后给p标签添加事件，那么问题就大了。所以再进行查询的时候，必须得去重。


query2加入的去重的功能，同时还支持querySelectorAll（注意：对于不符合CSS指定的selector，querySelectorAll会报错），它最大的功能，就是可以DIY属于自己的selector，可以根据自己的需求来指定selector，具体示例可以查看谈谈松散耦合、颗粒度中给出的代码例子。源码展示如下：



;(function(g){
	var D = document,fqueryAll=true;
	var _tag = function(tag,p){
		 return p.getElementsByTagName(tag &#124;&#124; &#34;*&#34;);
	}
	var contain=function(a,b){
		 return a.contains ? a!=b &#38;&#38; a.contains(b) : (a.compareDocumentPosition(b)==20);
	};
  var _queryMethod = {
		&#34;#&#34;:function(q,p){
       var bits = q.split(&#34;#&#34;),
	         tagName [...]]]></description>
		<wfw:commentRss>http://www.ilovejs.net/archives/1160/feed</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>网站再优化</title>
		<link>http://www.ilovejs.net/archives/1156</link>
		<comments>/archives/1156#comments-div</comments>
		<pubDate>Tue, 10 Aug 2010 16:44:56 +0000</pubDate>
		<dc:creator>Supersha</dc:creator>
				<category><![CDATA[性能优化]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[浏览器]]></category>

		<guid isPermaLink="false">http://www.ilovejs.net/?p=1156</guid>
		<description><![CDATA[
今天闲来无事，就用Firebug查看首页的HTTP瀑布图，测试页面加载时间，发现在外联的css和js上时间开销还是挺大的，虽然css和js都进行了gzip压缩，但是解析延迟在某些时候还是比较厉害，不是css解析延迟就是js解析延迟，在读取缓存的时候，也有一定的读取的时间开销。


鉴于这种情况，那么干脆就将首页的css和js都嵌入到页面中吧，把css放到head、js放到body闭合标签之前，反正这两个文件在gzip压缩的条件下也总共才三四K而已，而子页面里还是使用外联css和js的方式。


经过这样倒弄，首页加载速度平均有100ms的提升，欣喜若狂。更好笑的是yslow、page speed测试都得了满分，哈哈……


让首页嵌入css和js，而子页面外联的方式，主要是出于这样的一个目的：用户第一次浏览到首页的时候，页面可以尽快的呈现，而到了子页面，就加载css和js，这样的用户体验就有了一个类似于“稳步退化”的感觉，使得用户不会在起先的时候就有个不良感觉，而之后的访问，子页面就可以充分的利用缓存，因为子页面可能包含图片、flash等等，缓解HTTP的并发数。


还有，之前在浏览器下可能会有短暂的无样式与渲染样式之前切换的闪白，目前也得到了比较好的缓解。
]]></description>
		<wfw:commentRss>http://www.ilovejs.net/archives/1156/feed</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>谈谈松散耦合、颗粒度</title>
		<link>http://www.ilovejs.net/archives/1129</link>
		<comments>/archives/1129#comments-div</comments>
		<pubDate>Mon, 09 Aug 2010 18:07:06 +0000</pubDate>
		<dc:creator>Supersha</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[性能优化]]></category>
		<category><![CDATA[query]]></category>
		<category><![CDATA[松散耦合]]></category>
		<category><![CDATA[颗粒度]]></category>

		<guid isPermaLink="false">http://www.ilovejs.net/?p=1129</guid>
		<description><![CDATA[
“松散耦合”、“颗粒度”是相对于javascript库或者javascript框架来说的，它涉及的概念和包含的知识是很多的，而其中之一，就是说javascript库或者框架从整理来看是容易拆分，也容易自定义的组合，来实现特定需求的功能。之前有很多说法说YUI的编写方法才更接近于javascript的本质，虽然上手的门槛很高，但是对于一个真正的javascript程序员来说，反而更值得；而jQuery似乎另类了，改变了普通的编写javascript的编写方式，虽然说它封装的很好，“用最少的代码实现复杂的功能”，但是它的可读性就很差了，虽然门槛很低，毫无javascript基础的程序员在看了它的API文档之后都能够利用它写出很多丰富的效果。但是，作为程序员，这样下去行吗？


jQuery是毒药 &#8212;&#8212; 很多人都这么说。本人也举得，从一个程序员的成长来看，jQuery是弊大于利。我们更应该做的是学习它的原理和架构，而不是拿来用而已。


一个很经常会发生的问题：我只需要用到一个javascript库中的几个方法，却需要加载整个库的体积，而整个库封装的又十分复杂，拆分起来十分繁琐，怎么办？自己写呗……


一个javascript库的本意虽然说是为了提高开发效率、解决浏览器的兼容性问题、统一开发规范以及解决安全隐患等等。但是在设计javascript库的时候，我们是不是应该多留多点空间给使用者去DIY它的具体的功能，让使用者多点接触到javascript的本质，以及非常容易的缩减库的体积呢？就从这几点出发，YUI3是比较符合“松散耦合”、“颗粒度”的原则的，虽然说jQuery可以通过fn方法来扩展，但都是基于它整个已经封装好的库来说的。但是YUI3也有它的缺点：学习成本高、整体体积庞大、可能一步小心在use方法里多加载几个文件，或者使用&#8221;*&#8221;，那么需要异步加载的js文件也是很多的、以及它内部组件之间的依赖关系也是比较复杂的。


为了说明我的想法，首先从我编写的query鸡查询函数（目前还没完善，先拿来做例子）开始说起，我的想法是：只在query里实现最基本的selector查询，比如ID、class、tag、属性，之后用户可以自定义selector添加到查询函数当中，来实现自己特定的查询需求，从这点出发，改写了之前所写的query代码（之前的query.js），目前它只集合了ID、class、tag、属性选择器（或者也可以干脆连这些使用者都可以重新定义自己的功能函数，自己来实现，DIY很爽~），其他的自定义选择器都可以自己DIY，并且编写它的实现方式（留给使用者更多的编写底层代码的空间，爱怎么实现就怎么实现，方法是多样的），比如：给selector添加“:first”和“:l”来实现CSS3中的:first-child和:last-child的功能：


//q:表示当前的selector，比如“div p:first”，就是div和p:first，使用split通过空格切分的单个selector
//p:表示是上一级查询的结果，是数组类型的。
query.config.addSelector(&#34;:first&#34;,function(q,p){
  var tagName = q.split(&#34;:first&#34;)[0],
	  returnEl = [],
	  index=0,
	  tmp=null;
  for(var i=0,l=p.length;i&#60;l;i++){
	(tmp=query(tagName,[p[i]])) &#38;&#38; (returnEl[index++]=tmp[0]);
  }
  return returnEl;
});
///////////////////////////////////////////////////////////
query.config.addSelector(&#34;:l&#34;,function(q,p){
  var tagName = q.split(&#34;:l&#34;)[0],
	  returnEl = [],
	  index=0,
	  tmp=null;
  for(var i=0,l=p.length;i&#60;l;i++){
	(tmp=query(tagName,[p[i]])) &#38;&#38; (returnEl[index++]=tmp[tmp.length-1]);
  }
  return returnEl;
});


通过这样的方式，使得core核心代码尽可能的小，可扩展性强，同时也提供给使用者更多的编码空间，了解javascript这门语言的核心知识。目前经过压缩过后的query2-min.js和未压缩的query2.js提供浏览。并附带实例：《点点看呗》


扯谈完毕，欢迎拍砖~
]]></description>
		<wfw:commentRss>http://www.ilovejs.net/archives/1129/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>在IE中模拟Worker</title>
		<link>http://www.ilovejs.net/archives/1118</link>
		<comments>/archives/1118#comments-div</comments>
		<pubDate>Sat, 07 Aug 2010 13:50:29 +0000</pubDate>
		<dc:creator>Supersha</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[性能优化]]></category>
		<category><![CDATA[Worker]]></category>
		<category><![CDATA[多线程]]></category>

		<guid isPermaLink="false">http://www.ilovejs.net/?p=1118</guid>
		<description><![CDATA[
2010-8-8 update:在IE8下的eval是不支持下面两种的用法的，很杯具，都会提示“对象不支持此属性或方法”的错误。


//第一：
eval(&#34;onmessage=function(str){alert(str);}&#34;);
onmessage(&#34;shllo&#34;);
//第二：
var s = document.createElement(&#34;script&#34;),h=document.getElementsByTagName(&#34;head&#34;)[0];
s.text=&#34;onmessage=function(str){alert(str);}&#34;;
h.appendChild(s);

onmessage(&#34;hello&#34;);


说到这个，还发现一点很容易造成失误的地方：在浏览器解析过的script中的代码，浏览器不会重新对该script标签内的行内脚本、外联脚本执行，就算是重新给script标签定义行内脚本或者修改它的src来链接到其他的javascript脚本，浏览器都不会重新解析。

&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;- 提IE8 eval的兼容性分界线 &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;


从上一篇文章《Web Worker浅析》中，我们了解到Worker的思维是跟Ajax类似的，包括它也不支持跨域调用javascript文件，这说明底层的数据交互还是跟Ajax的模式类似（也有可能就是使用了Ajax的方式）。但是由于IE8及以下版本都不支持Worker，所以IE就不能充分利用Worker的优点来优化浏览器执行javascript代码的性能了。但是既然Worker跟Ajax类似，那么就让IE使用Ajax的方式来实现吧，这也不是不行的。


在IE中实现Worker机制，一个比较棘手的问题是postMessage、onmessage在主页面和Worker之间的调用问题，从代码上看，主页面是通过Worker类的实例化对象来调用postMessage、onmessage，而Worker里是直接声明和调用。所以在IE里，就可以模拟Worker的操作方式了。下面是我在IE下实现的方式：


在IE下重新定义Worker类，并且带有一个postMessage方法，这样就的话不会跟支持Worker的浏览器相冲突
使用Ajax的方式来加载外联的javascript文件，并通过eval执行返回的代码
通过一个全局的字面量对象，来实现两个文件之间的数据传输
不能改变标准的Worker类的编写方式，这个是一定要做到的

从上面的几点思路出发，编写了下面的实现代码：

(function(g){
   if(!document.all) return;

   var xhr=function(){
     var x = null;
     try{
	   x = new ActiveXObject(&#34;Msxml2.XMLHTTP&#34;);
	 }catch(e){
       x = new ActiveXObject(&#34;Microsoft.XMLHTTP&#34;);
	 }
	 return x;
   }

   [...]]]></description>
		<wfw:commentRss>http://www.ilovejs.net/archives/1118/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>overflow:hidden带来的问题</title>
		<link>http://www.ilovejs.net/archives/1105</link>
		<comments>/archives/1105#comments-div</comments>
		<pubDate>Thu, 05 Aug 2010 16:32:38 +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=1105</guid>
		<description><![CDATA[
即时更新：由@drunber提供的解决办法：设置父元素的padding或者border、float、position:absolute也可以解决问题，经测试验证通过。但是有一点需要说明的是：上下padding和border是必须要有数值的，设置为0无效。


但是对于动画来说，overflow:hidden是必须要设置的，否则里面的文本不会被遮盖。


&#8212;&#8212;&#8212;===========&#8212;&#8211; 即时更新分界线 &#8212;&#8212;===========&#8212;&#8212;&#8212;&#8211;


最近接到个需求，在搜索结果中添加下拉动画，高度和透明度都需要渐变。在测试过程中，遇到这样的一个问题：在一个div容器中包含了几个p标签，而且全在默认样式的情况，这样通过offsetHeight，clientWidth，scrollHeight等等获得div的高度，之后动态设置div的overflow样式属性为hidden，这样上面所获得的高度不准确了，《点击测试吧》，这样的后果就是动画被和谐了。


从这里的overflow:hidden对div的高度的差异可以看出：容器包含内容的解析原理。正常默认情况下，比如div包含一个p标签，这样div的宽高是会忽略p标签默认的margin值；但是一旦给div设置了overflow:hidden之后，div的实际宽高就需要加上p的margin值了。不过值得庆幸的是，在给div设置了overflow:hidden之后，通过offsetHeight等来获取div的宽高，是准确的。


从上面的分析中对于开头遇到的问题，就可以有三种方法来解决了：第一、在动态设置overflow:hidden之后来获取容器的高度，《点点测试吧》；第二、将p标签的margin清0处理，《再点点呗》；第三、干脆就不要使用p标签，改用没有默认margin的div吧，很勉强的方法，《最后点击测试下》。


Tip: 经过测试发现，设置overflow属性为hidden、auto都存在上面所说的情况。
]]></description>
		<wfw:commentRss>http://www.ilovejs.net/archives/1105/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>前端模板编程方式</title>
		<link>http://www.ilovejs.net/archives/1100</link>
		<comments>/archives/1100#comments-div</comments>
		<pubDate>Tue, 03 Aug 2010 08:06:14 +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=1100</guid>
		<description><![CDATA[
今天接触到一种使用javascript来实现的前端模板编写技巧，不需要后端的匹配替换，直接在浏览器端就可以完成。Not Using jQuery JavaScript Templates? You’re Really Missing Out。觉得思路不错，特此分享。


在浏览器端实现模板编程的难点之一，就是怎么编写HTML模板。这个在那篇文章中使用了script标签，这个觉得非常太神奇了，最神奇的是给script的type设置为text/html之后，它就不会使用javascript引擎来解析那些代码，也不会在页面上将HTML显示出来，同时也不报错。这都被发现了，牛逼！


知道了怎么保存模板之后，接下来的事情就是解析模板了，统一替换变量的声明方式，下面是我样例中使用的方式：


&#60;script id=&#34;test&#34; type=&#34;text/html&#34;&#62;
&#60;li&#62;&#60;a href=&#34;${url}$&#34;&#62;${name}$&#60;/a&#62;&#60;/li&#62;
&#60;/script&#62;

之后，就是通过javascript程序来解析了，我简单写了一个template函数来实现这个功能，《测试用例》：

function template(data,sEl,dEl){
  var html = sEl.nodeName &#38;&#38; sEl.innerHTML &#124;&#124; sEl,s = tmp = &#34;&#34;;
  data = data &#124;&#124; [];
  for(var i=0,l=data.length;i&#60;l;i++){
    tmp = html;
	for(var k in data[i]){
	  tmp = tmp.replace(RegExp(&#34;\\$\\{&#34;+k+&#34;\\}\\$&#34;,&#34;gi&#34;),data[i][k]);
	}
	s += tmp;
  }
  (dEl = [...]]]></description>
		<wfw:commentRss>http://www.ilovejs.net/archives/1100/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>无聊哥的代码 &#8212; “鸡”查询</title>
		<link>http://www.ilovejs.net/archives/1085</link>
		<comments>/archives/1085#comments-div</comments>
		<pubDate>Mon, 02 Aug 2010 16:35:45 +0000</pubDate>
		<dc:creator>Supersha</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[DOM]]></category>
		<category><![CDATA[query]]></category>
		<category><![CDATA[querySelectorAll]]></category>

		<guid isPermaLink="false">http://www.ilovejs.net/?p=1085</guid>
		<description><![CDATA[
刚上班，首先是文档哥，之后就是无聊哥了，真杯具。但是杯具下就好了，人不杯具。消遣的最好方式就是练练脑，写代码，query就是杯具下的产物。先出土个雏形，有时间还成无聊哥了再来扩展下。


query根据CSS规则来查询DOM，提供了基础的CSS选择符：


tag,.class,#id,[attr],tag[attr],tag[attr="value"]...

在测试跟jquery的查询速度比较的时候，再添加了对querySelectorAll（语法是：baseElement.querySelectorAll(selector)，这里的baseElement其实是可以为除了文本节点和空节点之外的任何的DOM节点的，别以为只是document而已）的支持。编写的代码中加入了本人认为不错的编写方式，如果你对阅读代码有兴趣，那就看看吧，欢迎提出更好的方式(如果这里显得难看了，就自己下载来看：query.js)：


;(function(g){
	var D = document,
		  _tag = function(tag,p){
		    return p.getElementsByTagName(tag &#124;&#124; &#34;*&#34;);
	    };
  var _queryMethod = {
		&#34;#&#34;:function(q){
			var bits = q.split(&#34;#&#34;),
				  tagName = bits[0],
				  id = bits[1],
				  element = D.getElementById(id);
			return tagName &#38;&#38; element.tagName.toLowerCase() != tagName ? [] : [element];
		},
		&#34;.&#34;:function(q,p){
			var bits = q.split(&#34;.&#34;),
				  tagName = bits[0],
				 [...]]]></description>
		<wfw:commentRss>http://www.ilovejs.net/archives/1085/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Web Worker浅析</title>
		<link>http://www.ilovejs.net/archives/1079</link>
		<comments>/archives/1079#comments-div</comments>
		<pubDate>Sat, 31 Jul 2010 18:06:31 +0000</pubDate>
		<dc:creator>Supersha</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Web Worker]]></category>
		<category><![CDATA[多线程]]></category>

		<guid isPermaLink="false">http://www.ilovejs.net/?p=1079</guid>
		<description><![CDATA[
2010-8-7 update:很悲剧的发现，Web Worker不支持跨域调用js文件。同时，经过测试，发现在Worker进程中的onmessage函数不能使用function onmessage(){}这种方式来声明，否则chrome、safari、opera不能执行它，切记~（实现Worker，FF比chrome、opera、safari兼容性好多了）


如果你使用window.onmessage=function(){}来声明onmessage方法，FF、Chrome等都提示window未定义的错误，这就很奇怪撂。难道Worker进程中不存在window这个对象？


&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211; 更新分界线 &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;


javascript单线程任务式的运行代码，这是大家普遍都知道的事情，有时候为了模拟多线程，会使用setTimeout/setInterval的方式，但是这个并不能解决实质的问题。Web Worker &#8212; javascript的“多核”时代来了！


Worker也已经出现的比较早了，记得当初首先是在Mozilla网站看到关于它的语法和特点介绍，今天在逛Opera看到了关于它的说明文档：Web Workers rise up!。觉得来详细的分析下它的原理是很有必要的了。下面是我对它的一点点看法：


Web Worker的基本原理就是在当前javascript的主线程中，使用Worker类来独辟一个新的线程，来处理外联的一个javascript文件，起到互不阻塞执行的效果，并且提供主线程和新线程之间数据交换的接口：postMessage，onmessage。而它的数据交换方式有点类似于Ajax的异步请求，都是浏览器“暗地里”传输的。下面是我分析之后得出的一个流程图：




从上面的流程图的数据交换方式是这样的（结合下面的DEMO来查看）：主线程通过实例化Worker类，来开辟一个新的进程，这个进程就会执行实例化Worker时指定的js文件，如果需要交换数据，则主线程通过Worker对象的postMessage方法来发送数据给新进程的js文件，新进程的js通过onmessage函数来接收主线程发送来的数据，经过处理之后，又使用postMessage方法发送回去，最后主线程通过Worker类的onmessage方法来接收新线程的js发送经过处理后的数据，over，这样就结束了两个线程之间的数据交互。


//worker.js
onmessage = function (evt){
   var d = evt.data;//通过evt.data获得发送来的数据
   postMessage(d+&#34;双核时代来啦&#34;);//再发送回去，礼尚往来
}


//main thread
var w = new Worker(&#34;worker.js&#34;);
w.postMessage(&#34;javascript&#34;);
w.onmessage = function(evt){
   alert(evt.data);//获取新线程的js发送来的数据
}


原理看起来很简单，但是在接触它的时候，有几个疑问在脑子里转：


Worker类接收js文件的url为参数，是否可以接收js代码字符串呢？
如果外联的js文件处理的时间很长，这样主线程的Worker对象的onmessage和postMessage执行会不会报错？
会不会存在编码问题？


经过测试之后，答案一一揭晓：Worker类不能够接收js代码字符串，比如：&#8221;new Worker(&#8216;onmessage=function&#8230;&#8217;)&#8221;；onmessage在这里是一种类似于click等的事件，它会在接收到数据之后触发，所以不用顾虑外联js文件处理的时间问题；因为Worker类的参数是一个url，它就会向服务器请求这个文件，发送一个HTTP请求，这里就又回归到Ajax的模式了，不过要注意编码问题。


还有一点需要注意的是：在外联js文件中，onmessage方法的声明方式千万别带上var，否则在Chrome,Safari,Opera下会失效，FF在有没有var都可以。


测试用例：《有var》，《无var》
]]></description>
		<wfw:commentRss>http://www.ilovejs.net/archives/1079/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>避免丑陋的if逻辑的新技巧</title>
		<link>http://www.ilovejs.net/archives/1075</link>
		<comments>/archives/1075#comments-div</comments>
		<pubDate>Fri, 30 Jul 2010 14:36:27 +0000</pubDate>
		<dc:creator>Supersha</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[三元运算符]]></category>

		<guid isPermaLink="false">http://www.ilovejs.net/?p=1075</guid>
		<description><![CDATA[我写代码时对if逻辑是比较反感的，说不出原因，用户体验不爽，因此总会使用三元运算符来规避if逻辑，看起来代码量少，简洁。对于操作单条的代码，这种方式就可以很容易的使用三元运算符来替换，比如：

if(flag){
  doSth();
}else{
  doAnotherSth();
}
//可以替换为：
flag ? doSth() : doAnotherSth();

单条的很容易，但是对于多条操作语句呢？这时候该怎么来避免使用if。答案还是从三元运算符中找，例如：

if(flag){
  c = &#34;ss&#34;;
  d =&#34;none&#34;;
  e.style.display=&#34;block&#34;;
}else{
  c = &#34;cc&#34;;
  d =&#34;normal&#34;;
  e.style.display=&#34;none&#34;;
}
//这个时候，还是可以通过一点小技巧来实现的：
flag ? ( c = &#34;ss&#34;,d=&#34;none&#34;,e.style.display=&#34;block&#34;) : (c = &#34;cc&#34;,d=&#34;normal&#34;,e.style.display=&#34;none&#34;);

各个操作语句之间使用逗号“，”组合起来，再加上小括号，就可以执行了。为此，可以较少一些字节，也使得代码简洁起来。
]]></description>
		<wfw:commentRss>http://www.ilovejs.net/archives/1075/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Watch对象更新</title>
		<link>http://www.ilovejs.net/archives/1066</link>
		<comments>/archives/1066#comments-div</comments>
		<pubDate>Wed, 28 Jul 2010 20:19:41 +0000</pubDate>
		<dc:creator>Supersha</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Watch]]></category>
		<category><![CDATA[测试工具]]></category>

		<guid isPermaLink="false">http://www.ilovejs.net/?p=1066</guid>
		<description><![CDATA[这次对Watch对象添加了一个新方法：iterate。主要是用于这样的情况，同时测试多个指定循环次数的情况，比如可以同时指定1000、2000、3000、4000&#8230;等等，通过iterate方法，就可以查看到几个测试用例在这几个循环次数下的时间消耗，iterate的用法如下：

Watch.iterate({
  &#34;title&#34;:[&#34;getElementsByTagName&#34;,&#34;childNodes&#34;],
  &#34;loop&#34;:[1000,2000,4000,5000,10000,20000,40000,100000],
  &#34;interval&#34;:1500,
  &#34;fn&#34;:[
    function(){ document.getElementById(&#34;div&#34;).getElementsByTagName(&#34;p&#34;);},
    function(){  document.getElementById(&#34;div&#34;).childNodes;}
  ]
});

iterate方法带有一个对象字面量参数，这个对象字面量的参数的属性包括title数组、loop循环次数数组、interval更新显示的时间间隔、fn测试函数数组。说起来可能比较虚，看例子吧：Watch.iterate()。
]]></description>
		<wfw:commentRss>http://www.ilovejs.net/archives/1066/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>flush()和ob_flush();flush()组合的差别</title>
		<link>http://www.ilovejs.net/archives/1057</link>
		<comments>/archives/1057#comments-div</comments>
		<pubDate>Wed, 28 Jul 2010 11:25:10 +0000</pubDate>
		<dc:creator>Supersha</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[性能优化]]></category>
		<category><![CDATA[flush]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.ilovejs.net/?p=1057</guid>
		<description><![CDATA[
2010-7-29 Updates:

如果将render解析为“呈现”，即是将元素显示到视窗中，那么Nicholas的说法在大部分浏览器下是正确的，经过下面使用PHP方式的测试，在没有将闭合标签加载下来之前，页面无法显示h1标签内容，但是IE除外，它仍然显示内容和应用样式。

同时还有一点需要说明的是：一些文章说在head和body之间插入flush()方法来尽早的输出head的内容，以至于尽快的下载样式资源，这也是有一定道理的，但是由于刷新输出的head内容是不可见的，所以页面上还是会一片空白，等待内容的呈现。所以比较合理的做法是将内容分块，或者将页面内容分为head、body、footer等俺顺序使用flush刷新输出，这样就使得有一个比较流畅的页面显示效果。


本人的blog正在这样实践着……

&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;纠正分界线&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;

在Nicholas的一个PPT中看到了这句话“The browser won&#8217;t render a block-level element inside of &#60;body&#62;
until the closing tag has been received”，意思就是“在body中，浏览器在一个块级元素的闭合标签未加载下来之前不会渲染该元素”，第一次看到这样的说法，感到很奇妙，到底是不是真的呢？


首先，使用javasript来进行测试，在一个块级元素中嵌套一个脚本，来获取该块级元素的innerHTML，《测试用例》，测试结果上面的说法错误。


接着测块级元素的style，使用js输出块级元素的style属性值，《测试用例》，测试结果上面的说法错误。


接着使用PHP的方式，在块级元素的闭合标签前面加上&#60;php flush(); sleep(3); ?&#62;，来查看是否会刷新输出内容，测试结果就是文章标题中所说明的问题，使用flush()和ob_flush();flush()组合的结果是不同的，并且在不同的浏览器下行为又有所不同。《flush()》，《ob_flush();flush()》。


PHP的测试结果为：使用flush()的形式的时候，Opera、Chrome、Safari、IE并没有在flush执行的时候刷新输出前面的内容；使用ob_flush();flush()组合的时候，Opera、Chrome、Safari、IE可以刷新输出前面的内容，但是这里又有个小插曲，IE可以输出元素闭合标签之前的内容，并可以渲染样式，但是Opera、Chrome、Safari只输出该元素之前的内容，该元素内的文本内容不会刷新输出。或许大家没有看到我提及Firefox浏览器的情况，经过测试，Firefox杯具的是两种形式都不会刷新输出内容，需要等到整个HTML文档加载完成才显示页面。为此，应该避免下面的情况：


  &#60;div&#62;Hello baby,www.ilovejs.net is here...&#60;?php ob_flush();flush(); ?&#62;&#60;/div&#62;
  &#60;!--或者--&#62;
  &#60;div&#62;Hello baby,www.ilovejs.net is here...&#60;?php flush(); ?&#62;&#60;/div&#62;


经过这些测试，可以得到明显的结论：在输出刷新方面，尽量使用ob_flush();flush()组合，并且避免在HTML标签的闭合标签之前刷新输出。
]]></description>
		<wfw:commentRss>http://www.ilovejs.net/archives/1057/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>图片导航设计方案</title>
		<link>http://www.ilovejs.net/archives/1055</link>
		<comments>/archives/1055#comments-div</comments>
		<pubDate>Tue, 27 Jul 2010 09:18:43 +0000</pubDate>
		<dc:creator>Supersha</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[DOM]]></category>
		<category><![CDATA[event]]></category>
		<category><![CDATA[图片导航]]></category>

		<guid isPermaLink="false">http://www.ilovejs.net/?p=1055</guid>
		<description><![CDATA[
2010-7-29 Update:


在第一种实现方案中，如果图片的父元素设置了padding、margin之后，就会使得FF、Chrome等逻辑判断失误，而IE还完好。

&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-纠错分界线&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;

说“图片导航”或许很迷糊，我也迷糊不知道怎么描述，就是类似于Google、QQ空间、百度图片搜索中的在图片中出现上下箭头或者左右箭头来指示下一个和上一个图片的功能。昨天同事问到我这方面的实现方式，也就暂时想了两种。


之前查看过Google的方法是在图片上添加两个HTML元素作为逻辑操作对象（包括切换鼠标样式、点击事件等），这样就显得比较复杂了，需要确定图片的在页面中的位置、图片的宽高、之后还要判断鼠标的位置……QQ空间的相册导航，是在图片本身来操作逻辑的，这同我第一种方案很类似，而百度图片搜索结果页中图片导航是在图片的父元素中做逻辑的，这样就避免了图片大小对导航的干扰的问题（主要是如果图片太小，在图片上做导航就显得迷糊了，特别是鼠标的样式切换）。下面来说说我的方法。


第一种，直接在图片上做逻辑。事件参数e有这么两个参数，在FF等浏览器下是layerX,layerY，在IE下是offsetX,offsetY，用于在一个DOM元素触发事件的时候，鼠标在该元素上的偏移量。这个是好方法啊，在结合offsetHeight和offsetWidth，就可以直接在图片上做判断了，给图片添加mousemove、onclick事件来处理鼠标样式切换、点击事件逻辑等等。《测试用例1》，可是这种方法的一个缺点是：在IE6下，当鼠标移动到鼠标的时候，会默认的弹出一个框，很杯具。


第二中方式就是根据上面的技巧，在图片上覆盖一个div（或者其他的能覆盖的元素都成），覆盖就得获取到图片在页面中的坐标以及宽高了，通过offsetLeft和offsetTop可以方便的得到，兼容性也还好，对于不是非常复杂的DOM结构和CSS布局，应该都是没啥问题的。《测试用例》，这样就避免了IE6下弹出框的问题。不过这样代码就得写多几行了。

具体的实现方式可以查看上面给出了两个实例。
]]></description>
		<wfw:commentRss>http://www.ilovejs.net/archives/1055/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>javasript预读机制小析</title>
		<link>http://www.ilovejs.net/archives/1050</link>
		<comments>/archives/1050#comments-div</comments>
		<pubDate>Thu, 22 Jul 2010 12:26:25 +0000</pubDate>
		<dc:creator>Supersha</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[预读机制]]></category>

		<guid isPermaLink="false">http://www.ilovejs.net/?p=1050</guid>
		<description><![CDATA[
javasript的预读机制说的直白点就是其他语言中所谓的“编译”，在代码运行之前对代码进行review一遍，把一些使用var和function声明的变量和函数提起读进内存里，并分配空间，初始化为undefined。等到代码运行的时候再进行相应的赋值。

简单的预读原理，相信很多人都已经知道了，比如：

alert(test);  //output:undefined
var test = &#34;supersha&#34;;
//=========================
alert(typeof fn); //output:function
function fn(){}
//=========================
alert(typeof fn2); //output:undefined
var fn2 = function(){}


上面是非常普通的原理，大家都能理解。但是有两个对于新手来说比较难懂的方面：“函数第一，变量第二”、“作用域环境”。


“函数第一、变量第二”，在这里的意思是在预读过程中，当遇到使用function声明的函数的时候，会先预读，即时后面使用var声明了同名的变量，也不会在内存中覆盖；而使用var声明的变量会受到后面使用var声明的同名变量的覆盖。需要注意的是，使用var的形式声明的函数字面量在预读的时候也是被当作一个变量来对待，它会受到同名变量的覆盖。但是，这里所的覆盖有一个大前提，需要在同一个作用域内。这就是“作用域环境”的意思，需要明白这点：在不同的作用域内，使用var声明的同名变量、函数在预读的时候是互相不干扰的。比如：


var url = &#34;www.ilovejs.net&#34;;
function fn(){
  alert(url);  //output:undefined
  var url = &#34;www.ilovejs.com&#34;;
  alert(url); //output:www.ilovejs.com
}
fn();
alert(url); //output:www.ilovejs.ne

上面的情况就涉及到作用域环境的问题了，两个使用var声明的url变量在不同的作用域内，相当于“独立”的变量，互相不干扰。
]]></description>
		<wfw:commentRss>http://www.ilovejs.net/archives/1050/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>浅析Memoization</title>
		<link>http://www.ilovejs.net/archives/1040</link>
		<comments>/archives/1040#comments-div</comments>
		<pubDate>Tue, 13 Jul 2010 08:27:14 +0000</pubDate>
		<dc:creator>Supersha</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[性能优化]]></category>
		<category><![CDATA[lazy definition]]></category>
		<category><![CDATA[Memoization]]></category>

		<guid isPermaLink="false">http://www.ilovejs.net/?p=1040</guid>
		<description><![CDATA[
Memoization，简单的说就是优化计算机的性能，缓存那些重复性的函数操作和计算，使得第一次之后的调用可以直接从缓存中得到结果，而无需重新计算和运行复杂、费时的函数。这个跟Lazy Definition的原理是比较相似的，Lazy Definition主要是对函数进行重复定义，避免浏览器检测等恶心的事情。在javascript里实现Memoization的技术，Keith Gaughan做了相关的叙述：Memoization in JavaScript。特别是它对Fibonacci的优化让我特别的玩味。


对于Fibonacci普通的实现方式是：


//这个性能不咋的，函数调用太频繁了
function Fib(n) {
    if (n &#60; 2) { return n;}
    return Fib(n - 1) + Fib(n - 2);
}

而Keith Gaughan对它的实现方式用Memoization进行了优化：

var IterMemoFib = function() {
    var cache = [1, 1];
    var fib = function(n) {
      [...]]]></description>
		<wfw:commentRss>http://www.ilovejs.net/archives/1040/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>CSS2.1的容错机制</title>
		<link>http://www.ilovejs.net/archives/1032</link>
		<comments>/archives/1032#comments-div</comments>
		<pubDate>Wed, 07 Jul 2010 09:43:52 +0000</pubDate>
		<dc:creator>Supersha</dc:creator>
				<category><![CDATA[CSS]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[selector]]></category>
		<category><![CDATA[样式]]></category>
		<category><![CDATA[浏览器]]></category>

		<guid isPermaLink="false">http://www.ilovejs.net/?p=1032</guid>
		<description><![CDATA[
CSS2.1是当前普遍使用着的CSS版本，平时如果循规蹈矩的编写CSS，或许不会发现问题，可问题就是：如果想要保存的时候，不小心按Ctrl+s的时候多留了一个s在CSS文件里，问题就开始来鸟；或者是不小心在规则的大括号外边多写了一个分号……出错的事情是千奇百怪的，对于新手来说频率可能会高些。出现这样的问题的时候、调试起来你可能会感觉很莫名其妙，这就需要了解一下CSS2.1版本的容错机制了。


CSS2.1的容错方式总的来说就是：对于出现一些无效的属性、属性值、@-keywords等等，它就会忽视这些样式声明或者整个规则声明。对于无效的属性、属性名会忽视该样式声明，对于@-keywords中keywords无效时，会将整个@-keywords包含的样式声明都忽略掉。


既然CSS2.1有这个容错机制，那么还有其他一些平时比较容易忽略的错误导致的样式失效的问题，下面举例出一些实例，看完下面的实例，基本可以了解CSS解析器解析CSS代码的一些原理了。


不要在CSS每个规则之间插入除空格之外的无效字符或者插入不合CSS语法的注释，否则该无效字符之后的第一个规则无效，例如：

body{color:green;}.  /*这里不小心多了个点号就杯具了*/
p.ten{color:red; background-color:green;} /*这个规则是无效的*/
p.one{color:red;} /*这个有效*/

有一种情况比较特殊，当无效字符等使用大括号“{}”包含的时候，它下面的规则正常应用了，因为浏览器CSS解析器将它当作一条规则来处理。比如：

body{color:green;}
{.}
p.ten{color:red; background-color:green;} /*它可以work啦*/


跟上面对应的就是在样式中出现无效字符或者插入不合CSS语法的注释，则当前无效字符之后的第一条样式无效，例如：

p.one{border-style:solid; . color:#00c; font-weight:bold;}  /*color无效*/

但是有一种情况比较特殊，就是存在分号“;”的时候，前面带有无效字符也没影响。可能浏览器CSS解析器是将样式规则用分号进行拆分成数组，每个分号之前的样式不会影响下一个样式，比如：

p.one{border-style:solid; . ; color:#00c; font-weight:bold;} /*color有效*/

因此从这里，有可以引申出一个问题：当编写每一个样式的时候最后没有加上分号，当前样式的下一个样式就会无效，因为浏览器把它解析成一整个属性:属性值对了（如果只有一个样式，或者是最后那个样式没有加上分号，则没什么影响。根据数组的split原理，建议是最后那个样式不加分号，这样就减少一个空的数组元素），比如：

/*下面就杯具了*/
p.one{
  border-style:solid
  font-weight:bold
}
/*这还不错*/
p.one{
  border-style:solid;
  font-weight:bold
}


不要在颜色值(英文、十六进制等等)上加上双引号，否则该样式规则无效，例如：

body{color:"red";background-color:"green";}


给元素设置border的时候，如果没有设置border-color，则会使用字体的颜色来代替；如果没有设置border-width，则默认是medium。例如:

p.one{border-style:solid; color:#00c;}


在一些连写的CSS规则中，如果其中一个元素的规则声明出现错误，则整个规则无效，比如：

p.one,em @,strong{border-style:solid; color:#00c;} /*这里em @ 出错，造成整个规则失效*/



如果在一个规则中样式进行了重复定义，如果其中一个样式的值无效（或者为空），那么不会覆盖有效的值的样式，因为浏览器会忽略掉无效值的样式声明，比如：

p.ten{color:red; background-color:green;color:ss;} /*color还是red*/


规则声明不可以嵌套：p.ten{color:#00c;p.ten{color:#f00};background:#0c0}
在规则的特殊性方面，对元素声明样式时，将样式定义在它自身上和定义在它父元素上的优先级差别：将样式定义在子元素上，即使是使用标签类型的规则都比父元素使用ID、class、important等这样高优先级的都高，比如：span是p元素的子元素，p带有ID属性为ten

span{color:red;} /*文本的color样式还是red*/
body p#ten{color:green !important;}


对于无效的属性或者属性值，CSS解析器会直接忽略掉这些属性或者属性值，也就使得这条样式声明无效，比如：

img { float: left }       /* correct CSS 2.1 */
img { float: left [...]]]></description>
		<wfw:commentRss>http://www.ilovejs.net/archives/1032/feed</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>用于测试页面Repaint的firebug扩展 &#8212; Repeat Test</title>
		<link>http://www.ilovejs.net/archives/1020</link>
		<comments>/archives/1020#comments-div</comments>
		<pubDate>Mon, 05 Jul 2010 19:43:45 +0000</pubDate>
		<dc:creator>Supersha</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[性能优化]]></category>
		<category><![CDATA[firebug]]></category>
		<category><![CDATA[Firefox]]></category>

		<guid isPermaLink="false">http://www.ilovejs.net/?p=1020</guid>
		<description><![CDATA[
归家了，博客都没怎么更新，感觉有些不适应了。这几天忙里偷闲，研究了下firebug扩展的开发原理，倒弄了两三天，firebug的架构也确实比较复杂，而且发现Firefox下的扩展在开发中编写js代码并没有想象中的容易，平时认为合理的js代码，在Firefox的插件里跑起来，却总是会出现诸多错误，很纠结。仔细查看了firebug的源码中的xul文件，觉得firebug的架构和方法调用方式，也确实值得借鉴，语意化十足：利用xul文件来规划布局，js实现功能，css实现样式布局，properties格式的文件来储存文字信息……


《Repaint 跟踪浏览器的渲染》从这篇文章中了解到，原来Firefox还有一个独有的事件：MozAfterPaint供我们来测试页面Repaint的数据，这个事件的具体使用方式和参数设置可以查看前面给出链接中Mozilla的官方叙述。PJhome网站中给出的例子是需要通过使用Greasemonkey来自定义一个脚本，我感觉这有诸多不便：不便于操作；开始和结束等方面的不变……为此，我将这个功能集成到firebug下，基本上web开发人员都会安装firebug，所以倒是便利了许多。下面就来说说Repaint Test的具体使用方式：


首先用Firefox3.5以上的版本（因为MozAfterPaint事件是在3.5版本之后才受支持的）下载Repaint Test文件：Repaint Test，直接点击链接就可以安装了。
打开firebug主界面，其中就有一个叫“Repaint Test”的面板，点击它，就出现了它的操作按钮组：

Repaint Test面板下面有“Self start record”、“Start”、“Stop and Show”、“Clear”按钮，同时面板右边还有下拉菜单，提供了“Configuration”、“Zoom（文字大小）”、“Help”等功能。顾名思义，Configuration是用于配置扩展内部的一些属性。


“Self start record”按钮用于在页面加载后，在设置的时间内自动开始记录Repaint区域数据；“Start”按钮用于手动设置记录Repaint的开始；“Stop and Show”用于停止记录Repaint区域数据并显示Repaint区域（红色高亮显示），这里有定时器来显示每一个记录的Repaint数据。“Clear”按钮用于清空输出内容。

在这里需要明白的是：“Self start record”和“Stop and Show”按钮内部都设定了定时器，不过间隔时间可以自定义，在Configuration弹出框里可以设置。但是最后的展示输出Repaint区域数据都需要点击“Stop and Show”来完成。



还有，输出的每一项Repaint的区域数据，都可以点击，再现Repaint区域的高亮效果。


在PJhome中，还介绍了IE9提供了更多开放的接口供前端开发人员进行性能测试：《IE9允许前端开发获取到页面性能数据》，Very perfect！！但是IE系列总会有很多让人抹汗的地方，IE9的这套接口能否满足以后页面性能测试的需要，还有待测试和考验。


最后，欢迎大家对这个Repaint Test扩展进行测试和提出更好的建议，尽力去完善它的功能和使它在使用上更加的简便……
]]></description>
		<wfw:commentRss>http://www.ilovejs.net/archives/1020/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>随便写的一个Node代码</title>
		<link>http://www.ilovejs.net/archives/997</link>
		<comments>/archives/997#comments-div</comments>
		<pubDate>Sun, 27 Jun 2010 06:41:32 +0000</pubDate>
		<dc:creator>Supersha</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[DOM]]></category>
		<category><![CDATA[Node]]></category>
		<category><![CDATA[setAttribute]]></category>

		<guid isPermaLink="false">http://www.ilovejs.net/?p=997</guid>
		<description><![CDATA[2010-6-29 update

判断是IE6、7浏览器的方法还可以通过检测：document.documentElement.hasAttribute这个方法是否存在来判断。IE6、7下document.documentElement是不支持hasAttribute方法的；IE8、FF、Chrome、Opera等都支持。这样就可以避免丑陋的@cc_on判断方式了，不过在性能上，或许还是会@cc_on比较好。

&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;完美的分界线&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-
昨天想起了之前在口碑的时候就想写的一个代码：把HTML标签名作为方法来连缀性的插入元素，比如下面的操作方式：

var root=Node(&#34;div&#34;,&#34;&#34;,{&#34;id&#34;:&#34;test&#34;,&#34;class&#34;:&#34;div&#34;,&#34;onclick&#34;:&#34;alert(this.innerHTML);&#34;,
&#34;style&#34;:&#34;background-color:#f00;&#34;})
.h1(&#34;P Element in DIV Element&#34;,{&#34;class&#34;:&#34;p&#34;})
.em(&#34;EM Element&#34;,{&#34;class&#34;:&#34;em&#34;}).appendTo(document.body);
//==========================================
Node(&#34;div&#34;,&#34;&#34;,{&#34;class&#34;:&#34;div&#34;,&#34;onclick&#34;:&#34;alert(this.innerHTML);&#34;})
.h1(&#34;P Element in DIV Element&#34;,{&#34;class&#34;:&#34;p&#34;})
.em(&#34;EM Element&#34;,{&#34;class&#34;:&#34;em&#34;}).appendTo(root);


如上代码所示，将HTML的标签名作为方法，在Node方法执行的时候就动态生成一个DOM元素，之后调用的HTML标签名形式的方法会一步一步的appendChild到前面的一个DOM元素中，调用每一个HTML标签名形式的方法都会动态生成一个相应的DOM元素，最后调用appendTo或者beforeTo方法将Node方法动态生成的DOM元素插入到这两个方法参数指定的父元素中。同时，还可以设置DOM元素的attribute、style、text。是不是有点意思呢？^_^


但是在写这个代码的时候，遇到的最大困难，就是setAttribute了，一来IE6、7对一些属性使用了不同的DOM属性名，在设置style的时候，也存在cssText和直接setAttribute style的差别，这些都是比较纠结的。幸好，下面的几个知识点可以解决大部分的冲突：


利用IE下setAttribute方法的第三个参数，可以解决IE6、7下对于一些属性大小写的差别。《setAttribute Method》、《setAttribute()方法参数问题》
对于一些IE6、7跟其他浏览器的属性名完全不同（比如：class、for、checked、selected），这可以通过一个字面量对象来纠正，可以看下面我写的源码的解决办法。
IE6、7无法给onxxx属性（事件）直接赋值为字符串，需要赋给它函数才行。这个就需要做判断了，本人使用了@cc_on来判断IE的版本，并通过new Function的方式给IE6、7设置onxxx这样的属性。
同时，还有一个小陷阱，在HTML标签中直接声明onxxx属性的时候，不能够使用匿名函数的方式，比如:onclick=&#8221;function(){alert(&#8216;hello&#8217;);}&#8221;，这将会造成语法错误。


下面是本人写的Node代码，《测试示例》^_^:

;(function(w) {
  var D = document,_node = null,_root = null,
     special = {
       &#34;class&#34;: &#34;className&#34;,
       &#34;checked&#34;: &#34;defaultChecked&#34;,
       [...]]]></description>
		<wfw:commentRss>http://www.ilovejs.net/archives/997/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Script DOM Element加载js文件的延伸</title>
		<link>http://www.ilovejs.net/archives/986</link>
		<comments>/archives/986#comments-div</comments>
		<pubDate>Fri, 25 Jun 2010 18:43:44 +0000</pubDate>
		<dc:creator>Supersha</dc:creator>
				<category><![CDATA[性能优化]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Script DOM Element]]></category>
		<category><![CDATA[图片]]></category>

		<guid isPermaLink="false">http://www.ilovejs.net/?p=986</guid>
		<description><![CDATA[
Script DOM Element动态加载js可以使得js文件跟其他资源并行加载并异步执行，这是我们都知道的事实。但是有一点，或许有些人没有想到，js脚本在何时才会开始加载？


话说多了不足为信，看一个简单的测试：《测试js何时开始加载（用firebug查看HTTP瀑布图，或者HTTPWatch、Inspection等等均可）》，代码示例如下


var s = document.createElement(&#34;script&#34;);
s.setAttribute(&#34;src&#34;,&#34;test.js&#34;);

var l =document.createElement(&#34;link&#34;);
l.setAttribute(&#34;href&#34;,&#34;/wp-content/c/style.css&#34;);
l.setAttribute(&#34;rel&#34;,&#34;stylesheet&#34;);

var img = new Image();
img.setAttribute(&#34;src&#34;,&#34;/wp-content/uploads/2010/06/performance.png&#34;);
//document.body.appendChild(img);
document.body.appendChild(l);
document.body.insertBefore(s,document.body.lastChild);


通过上面的测试发现：图片先加载，之后是js，最后是css文件。但是看上面的代码，图片并没有插入到文档中，但是它还是加载了；虽然js先于图片声明，但是却在图片之后加载；CSS虽然后于js声明，但是先于js加载。


这就有意思了，通过上面的测试说明：使用new Image声明的图片，在设置它的src属性之后就会开始加载；js和css文件在插入到文档之后才开始加载。通过这个特点，我们在性能优化方面就可以再总结几点想法了：


通过使用Script DOM Element的方式加载js的时候，虽然说是可以同其他资源并行加载和异步执行，但是如果加载的js可以在页面加载完成之后才需要起作用的，可以在&#60;/body&#62;前面来声明并插入到页面中，从而可以多让其他资源并行加载，而js最后加载并执行，加快页面的加载速度，这样的话将js插入到head和document.body都一样的效果。
同样使用Link DOM Element的方式加载css文件的时候（如果一定要这样做的话），因为样式表关系到整个页面的布局和样式渲染，所以它需要尽早的被加载进来并开始渲染，以免造成页面内容显示的延迟和IE下“白屏”的问题。
在优化图片加载的需求上，虽然图片加载是并行的，但是浏览器并行加载资源的数目是受到限制的，对于那些不是在浏览器第一屏（打开网页时在浏览器视窗内看到的内容）看到的图片、图片Tab组件、图片列表等等，可是使用上面的方式动态来插入，在页面其他重要的内容和资源都加载完毕的时候，其次的图片动态的插入，使得浏览器开始加载这些的图片。对于加快页面的显示速度，这也是不错的方式。

]]></description>
		<wfw:commentRss>http://www.ilovejs.net/archives/986/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
