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

<channel>
	<title>写意生活 &#187; Web开发</title>
	<atom:link href="http://x1989.com/category/webdev/feed" rel="self" type="application/rss+xml" />
	<link>http://x1989.com</link>
	<description>小谢的Blog — 认真生活 快乐工作 专注Web前后端开发&#124;移动平台</description>
	<lastBuildDate>Sat, 08 Oct 2011 10:21:54 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>PHP模拟BigPipe</title>
		<link>http://x1989.com/a/469.html</link>
		<comments>http://x1989.com/a/469.html#comments</comments>
		<pubDate>Sat, 08 Oct 2011 08:20:58 +0000</pubDate>
		<dc:creator>xhowhy</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Web开发]]></category>
		<category><![CDATA[BigPipe]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[前端]]></category>

		<guid isPermaLink="false">http://x1989.com/?p=469</guid>
		<description><![CDATA[前不久新浪微博改版，前端引入了BigPipe（最早是Facebook提出的），页面载入速度嗖嗖嗖地上去了。。那末为神马BigPipe能这么快呢？

与AJAX相似，BigPipe使页面可以按区块渲染。但与AJAX不同的是，BigPipe不需要在页面载入后再通过XMLHttpRequest向服务器发起异步请求，而是（通过使用缓冲区）在页面载入过程中先输出页面布局，并在HTML中预留各个页面区块（Facebook称为Pagelet），在页面底部才输出Javascript代码，DOM操作，从而对区块进行内容填充，也就是把内容赋给innerHTML。

<span class="readmore"><a href="http://x1989.com/a/469.html" title="PHP模拟BigPipe">阅读全文——共1439字</a></span>]]></description>
			<content:encoded><![CDATA[<p>前不久新浪微博改版，前端引入了BigPipe（最早是Facebook提出的），页面载入速度嗖嗖嗖地上去了。。那末为神马BigPipe能这么快呢？<br />
与AJAX相似，BigPipe使页面可以按区块渲染。但与AJAX不同的是，BigPipe不需要在页面载入后再通过XMLHttpRequest向服务器发起异步请求，而是（通过使用缓冲区）在页面载入过程中先输出页面布局，并在HTML中预留各个页面区块（Facebook称为Pagelet），在页面底部才输出Javascript代码，DOM操作，从而对区块进行内容填充，也就是把内容赋给innerHTML。<br />
这么做的好处是，在页面加载的过程中，把一些响应时间相对较长的输出放到了页面底部，而页面整体轮廓先显示出来，减少用户的等待时间；此外，与Ajax相比，BigPipe不需要进行多次请求就能完全显示内容，降低了服务器的负担。<br />
下面用PHP模拟一下BigPipe，代码里用sleep(1)模拟一些运算的时间损耗（要先关闭Apache的GZip）：</p>
<pre>
&lt;!doctype&gt;
&lt;html&gt;
&lt;head&gt;
	&lt;meta charset=&quot;utf-8&quot; /&gt;
	&lt;title&gt;PHP模拟BigPipe&lt;/title&gt;
&lt;/head&gt;
&lt;style&gt;
.section{height:200px;}
#con1{background:#ef8090;}
#con2{background:#fef000;}
#con3{background:#19c000;}
&lt;/style&gt;
&lt;body&gt;
	&lt;div class=&quot;wrapper&quot;&gt;
		&lt;div class=&quot;section&quot; id=&quot;con1&quot;&gt;页头内容，正在加载……&lt;/div&gt;
		&lt;div class=&quot;section&quot; id=&quot;con2&quot;&gt;正文内容，正在加载……&lt;/div&gt;
		&lt;div class=&quot;section&quot; id=&quot;con3&quot;&gt;页尾内容，正在加载……&lt;/div&gt;
	&lt;/div&gt;
	&lt;?php
	/*
	 * 输出缓存区
	 */
	function flush_now(){
		ob_flush();
		flush();
	}
	flush_now();
	?&gt;

	&lt;?php sleep(1);?&gt;
	&lt;script&gt;
		document.getElementById(&quot;con1&quot;).innerHTML = &quot;&lt;?php echo str_repeat(\'内容1\', 200) ?&gt;&quot;;
	&lt;/script&gt;
	&lt;?php flush_now()?&gt;

	&lt;?php sleep(1);?&gt;
	&lt;script&gt;
		document.getElementById(&quot;con2&quot;).innerHTML = &quot;&lt;?php echo str_repeat(\'内容2\', 200) ?&gt;&quot;;
	&lt;/script&gt;
	&lt;?php flush_now()?&gt;

	&lt;?php sleep(1);?&gt;
	&lt;script&gt;
		document.getElementById(&quot;con3&quot;).innerHTML = &quot;&lt;?php echo str_repeat(\'内容3\', 200) ?&gt;&quot;;
	&lt;/script&gt;
	&lt;?php flush_now()?&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre>
<p>这样，打开页面后，页头、正文和页尾的内容一开始显示的是“正在加载……”，但随后内容会逐一显示出来，肿么样，很神奇吧。<br />
<strong>但话说回来，这只是模拟的BigPipe，因为每个区块的内容输出之间是阻塞的，需要等待前一个区块处理完了，才能接着处理后一个。而要真正实现BigPipe就得使用多线程，可以通过CURL的异步模式或者pctnl。</strong> </p>
]]></content:encoded>
			<wfw:commentRss>http://x1989.com/a/469.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>关于一些编程语言的运算符“优先级”</title>
		<link>http://x1989.com/a/436.html</link>
		<comments>http://x1989.com/a/436.html#comments</comments>
		<pubDate>Tue, 12 Jul 2011 11:35:06 +0000</pubDate>
		<dc:creator>xhowhy</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Web开发]]></category>
		<category><![CDATA[其他文章]]></category>
		<category><![CDATA[前端开发]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[运算符优先级]]></category>

		<guid isPermaLink="false">http://x1989.com/?p=436</guid>
		<description><![CDATA[Tips:这个问题是铁军师兄发现并提出的，我写篇博客梳理一下。

当我们在学习一门编程语言的时候，我们经常会看到类似这样的一句话：运算符优先级是一套规则。该规则在计算表达式时控制运算符执行的顺序。具有较高优先级的运算符先于较低优先级的运算符执行。

那么事实是不是果真如此呢，下面让我们用Javascript等几门语言为例来验证一下。

<span class="readmore"><a href="http://x1989.com/a/436.html" title="关于一些编程语言的运算符“优先级”">阅读全文——共1627字</a></span>]]></description>
			<content:encoded><![CDATA[<p>Tips:这个问题是<a href="http://www.yigle.net/" title="铁军" target="_blank">铁军</a>师兄发现并提出的，我写篇博客梳理一下。<br />
当我们在学习一门编程语言的时候，我们经常会看到类似这样的一句话：运算符优先级是一套规则。该规则在计算表达式时控制运算符执行的顺序。具有较高优先级的运算符先于较低优先级的运算符执行。<br />
那么事实是不是果真如此呢，下面让我们用Javascript等几门语言为例来验证一下。<br />
首先，在官方的ECMA-262/Core JavaScript手册以及权威的MDN Docs中，分别是这样介绍Javascript运算符优先级的：</p>
<blockquote><p>
All operators have a pre-defined execution priority or precedence. Within a given complex expression, operations will be performed in order of priority.
</p></blockquote>
<blockquote><p>
Operator precedence determines the order in which operators are evaluated. Operators with higher precedence are evaluated first.
</p></blockquote>
<p>两段介绍的意思大致是一样的，都是说运算符优先级决定了运算符执行的先后顺序。运算符优先级高的运算符会被先执行（计算）。我们以往的编程经验似乎也在告诉我们这是真理，然而请先看下面一段代码：</p>
<pre>
var a=1;
function fn(){
    console.log(a);
}
var b = a++ + fn();
</pre>
<p>按照Javascript官方手册上对运算符优先级的定义以及的运算符优先级表（如图所示或参考http://rx4ajax-jscore.com/ecmacore/operator/predence.html），我们可以推算运行结果：在最后一行代码中，由于函数调用的括号运算符“()”优先级比自增运算符“++”和算术运算符“+”都要高，所以会先被执行。所以在控制台中被log的a的值应该是1。而事实上，结果是2。这说明了什么？——虽然“()”运算符的优先级比“++”要来得高，但a++却先于fn()被执行。<br />
<a href="http://x1989.com/wp-content/uploads/2011/07/javascriptPrecedence.png" target="_blank"><img src="http://x1989.com/wp-content/uploads/2011/07/javascriptPrecedence-300x98.png" alt="javascript优先级" title="javascriptPrecedence" width="300" height="98" class="alignnone size-medium wp-image-441" /></a><br />
图节选自Javascript运算符优先级表（http://rx4ajax-jscore.com/ecmacore/operator/predence.html）<br />
那么在Javascript中是这种状况，在其他语言中又会是什么情况呢？随后，我们分别测试了PHP、C/C++、Java以及C#版本的代码（Python和Ruby中没有自增运算符）。猜猜结果各是什么？<br />
PHP版：</p>
<pre>
$a=1;
function fn($a1){
    echo $a1;
}
$b = $a++ + fn($a);
</pre>
<p>C++版：</p>
<pre>
#include "stdafx.h"
#include &lt;iostream&gt;
using namespace std;
int fn(int a1)
{
	cout&lt;&lt;a1;
	return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
	int a = 1;
	int b = a++ + fn(a);
	int i;
	cin&gt;&gt;i;
	return 0;
}
</pre>
<p>揭晓答案：<br />
只有C/C++输出了1，其他语言都输出了2。<br />
这样看来似乎最传统的编译型语言C/C++能得出与其运算符优先级定义相符合的结果。而事实上关于运算符优先级，PHP手册是这样定义的：</p>
<blockquote><p>
The precedence of an operator specifies how “tightly” it binds two expressions together.
</p></blockquote>
<p>意思是运算符优先级决定了两个表达式之间“紧密程度”——也就是说代码的组合方式。这么一来PHP为什么输出2就能解释了。而C#和Java的代码，如果这么解释也能解释得清楚。不过在Java的运算符中，并没有函数调用的“()”运算符。C#当中却是有的。更有趣的是，在C/C++中，前自增/减运算符“++/&#8211;”的优先级居然排在了函数调用运算符“()”的前面，仅次于“::”运算符。<br />
结论：混乱啊。。</p>
]]></content:encoded>
			<wfw:commentRss>http://x1989.com/a/436.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>一道Javascript面试题</title>
		<link>http://x1989.com/a/432.html</link>
		<comments>http://x1989.com/a/432.html#comments</comments>
		<pubDate>Mon, 11 Jul 2011 07:05:27 +0000</pubDate>
		<dc:creator>xhowhy</dc:creator>
				<category><![CDATA[Web开发]]></category>
		<category><![CDATA[前端开发]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[面试题]]></category>

		<guid isPermaLink="false">http://x1989.com/?p=432</guid>
		<description><![CDATA[var n = 2;

var showNumber = function(){

    n = 1;

<span class="readmore"><a href="http://x1989.com/a/432.html" title="一道Javascript面试题">阅读全文——共96字</a></span>]]></description>
			<content:encoded><![CDATA[<pre lang="javascript">
var n = 2;
var showNumber = function(){
    n = 1;
    alert(n);
}
(function(){
    n=3;
    alert(n);
})()
</pre>
<p>你能说出alert出的内容并解释其原因吗？</p>
]]></content:encoded>
			<wfw:commentRss>http://x1989.com/a/432.html/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>事件委托在jQuery和KISSY内核中的应用</title>
		<link>http://x1989.com/a/459.html</link>
		<comments>http://x1989.com/a/459.html#comments</comments>
		<pubDate>Mon, 11 Jul 2011 02:50:50 +0000</pubDate>
		<dc:creator>xhowhy</dc:creator>
				<category><![CDATA[Web开发]]></category>
		<category><![CDATA[前端开发]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[Kissy]]></category>
		<category><![CDATA[事件委托]]></category>

		<guid isPermaLink="false">http://x1989.com/?p=459</guid>
		<description><![CDATA[一直觉得jQuery中的 .live() 方法很神奇，居然可以对动态加入的元素进行绑定。今天终于弄明白了，原来这是通过使用事件委托实现的。



   $('a').live('click', function(){

<span class="readmore"><a href="http://x1989.com/a/459.html" title="事件委托在jQuery和KISSY内核中的应用">阅读全文——共673字</a></span>]]></description>
			<content:encoded><![CDATA[<p>   一直觉得jQuery中的 .live() 方法很神奇，居然可以对动态加入的元素进行绑定。今天终于弄明白了，原来这是通过使用事件委托实现的。</p>
<pre>
   $('a').live('click', function(){
      //code block1
   })
   </pre>
<p>   上面的这段代码可以约等于（但不完全等于，总结中说明了为什么）：</p>
<pre>
   $(document).bind('click', function(e){
      if(e.srcElement.tagName == 'a'){
         //code block1
      }
   })
   </pre>
<p>   此外，jQuery还有一个 .delegate() 方法，可以实现接近 .live() 的效果：</p>
<pre>
   $('#container').delegate('a','click',function(){
      //code block2
   })
   </pre>
<p>   jQuery在文档中查找#container，并使用click事件和&#8217;a'这一CSS选择器作为参数，把函数绑定到$(&#8216;#container&#8217;)上。任何时候只要有事件冒泡到$(&#8216;#container&#8217;)上，它就查看该事件是否是click事件，以及该事件的目标元素是否与CSS选择器相匹配。如果两种检查的结果都为真的话，它就执行绑定的函数。<br />
   在KISSY 1.2版本中也引入了 .delegate() 方法。<br />
   <strong>这两种方法中，个人觉得还是 .delegate() 方法效率高。因为 .live() 方法需要把选择器匹配到的元素都包装成jQuery对象；而 .delegate() 方法只在委托的节点上监听冒泡事件。感觉用 .live() 方法进行事件委托比较鸡肋啊，可能这也是为什么其他js框架没有类似方法的原因吧。</strong></p>
]]></content:encoded>
			<wfw:commentRss>http://x1989.com/a/459.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>javascript元编程创建DOM节点</title>
		<link>http://x1989.com/a/407.html</link>
		<comments>http://x1989.com/a/407.html#comments</comments>
		<pubDate>Fri, 06 May 2011 02:53:31 +0000</pubDate>
		<dc:creator>xhowhy</dc:creator>
				<category><![CDATA[Web开发]]></category>
		<category><![CDATA[前端开发]]></category>
		<category><![CDATA[dom]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[元编程]]></category>

		<guid isPermaLink="false">http://x1989.com/?p=407</guid>
		<description><![CDATA[在使用javascript创建DOM节点的过程中，难免要使用document.createElement、setAttribute、document.createTextNode等冗长、还有浏览器兼容性问题的节点操作方法，虽然有人提议使用字符串拼接后，再使用.innerHTML=可以降低创建节点的成本，而且还有更好的性能，但在我印象中innerHTML并不能适应所有需求（具体神马需求我也忘了），所以下面给大家介绍一种使用javascript元编程技巧来动态创建节点的方法。

那么什么是元编程呢？了解Ruby的同学知道，Ruby的风靡离不开Ruby on Rails(RoR)框架的推动。RoR框架通过魔幻实现质朴的方式，把很多需要用其他语言实现的功能用Ruby来实现，最经典当属RoR框架的ActiveRecord。让我们看一下下面这段代码：

<span class="readmore"><a href="http://x1989.com/a/407.html" title="javascript元编程创建DOM节点">阅读全文——共3522字</a></span>]]></description>
			<content:encoded><![CDATA[<p>在使用javascript创建DOM节点的过程中，难免要使用document.createElement、setAttribute、document.createTextNode等冗长、还有浏览器兼容性问题的节点操作方法，虽然有人提议使用字符串拼接后，再使用.innerHTML=可以降低创建节点的成本，而且还有更好的性能，但在我印象中innerHTML并不能适应所有需求（具体神马需求我也忘了），所以下面给大家介绍一种使用javascript元编程技巧来动态创建节点的方法。<br />
那么什么是元编程呢？了解Ruby的同学知道，Ruby的风靡离不开Ruby on Rails(RoR)框架的推动。RoR框架通过魔幻实现质朴的方式，把很多需要用其他语言实现的功能用Ruby来实现，最经典当属RoR框架的ActiveRecord。让我们看一下下面这段代码：</p>
<pre lang="ruby">
person = Person.find_by_email('xxx@x1989.com')
person.age = 23
person.save
</pre>
<p>上述代码可以用SQL语句替换，如下所示：</p>
<pre lang="SQL">
SELECT * FROM person WHERE email = 'xxx@x1989.com'
UPDATE person SET age = 23 WHERE email = 'xxx@x1989.com'
</pre>
<p>即使不会Ruby和SQL的人也可以看出，采用Ruby语法方式更自然。而正是Rails通过元编程技巧，让我们无须在一个程序中混用两种不同的语言。维基百科上元编程的定义：</p>
<blockquote><p>编写一些程序来提前生成一些数据或代码供运行时使用，用来生成这些数据信息或代码的程序称为元程序（MetaProgram），编写这种程序就称为元编程（MetaProgramming）。</p></blockquote>
<p>另一种说法：</p>
<blockquote><p>元编程是指某类计算机程序的编写，这类计算机程序编写或者操纵其它程序（或者自身）作为它们的数据，或者在运行时完成部分本应在编译时完成的工作。</p></blockquote>
<p>那么，我希望用javascript实现”create_”+任意HTML5标签名的动态节点生成函数，比如用create_form、create_div、create_input来生成对应名称的节点，使用下面的api：</p>
<pre>
//①创建只含有文本的节点
var span = create_span('hello world');
或不含文本的节点
var br = create_br();

//②可以在参数1中以对象字面量来定义属性
var input = create_input({
    'type': 'text',
    'size': 20,
    'value': '123'
})

//③用参数2定义文本节点
var a = create_a({
    'href': 'http://www.google.com.hk',
    'title': '谷歌搜索',
    'target': '_blank',
    'rel': 'xxxxx',
    'costom_attr': '自定义属性',
}, '搜索');

//④参数2可以是节点 参数3（可选）是文本节点
var div = create_div({}, create_img({'src': 'http://www.google.com.hk/intl/zh-CN/images/logo_cn.png'}), '这是logo')

//⑤参数2也可以是节点构成的数组
var ul = create_ul({
	'class': 'list1'
}, [create_li('项目1'), create_li('项目2'), create_li('项目3')]);
</pre>
<p>实现方式：</p>
<pre lang="javascript">
void function() {
    //支持以"create_"+任意HTML5标签名的动态节点生成函数
    var doc = document, win = window,
    //HTML5标签:
    tags = ["a", "abbr", "acronym", "address", "applet", "area", "article", "aside", "audio", "b", "base", "basefont", "bdo", "big", "blockquote", "body", "br", "button", "canvas", "caption", "center", "cite", "code", "col", "colgroup", "command", "datagrid", "datalist", "datatemplate", "dd", "del", "details", "dialog", "dir", "div", "dfn", "dl", "dt", "em", "embed", "event-source", "fieldset", "figure", "font", "footer", "form", "frame", "frameset", "h1", "h2", "h3", "h4", "h5", "h6", "head", "header", "hr", "html", "i", "iframe", "img", "input", "ins", "isindex", "kbd", "label", "legend", "li", "link", "m", "map", "menu", "meta", "meter", "nav", "nest", "noframes", "noscript", "object", "ol", "optgroup", "option", "output", "p", "param", "pre", "progress", "q", "rule", "s", "samp", "script", "section", "select", "small", "source", "span", "strike", "strong", "style", "sub", "sup", "table", "tbody", "td", "textarea", "tfoot", "th", "thead", "time", "title", "tr", "tt", "u", "ul", "var", "video", "xmp"];
    for (var i = 0; tags[i]; i++) {
        //闭包是个好东东
        win['create_' + tags[i]] = function(tag) {
            return function(attrs, childNode, textNode) {
                return createNode(tag, attrs, childNode, textNode)
            }
        } (tags[i]);
    }
    var createNode = function (tagName, attrs, childNode, textNode) {
        //创建以tagName命名的节点
        var node = doc.createElement(tagName);

        //处理attrs参数 设置节点属性
        typeof attrs === 'string' ? createTextNode(node, attrs) : createAttributeNode(node, attrs); //创建并设置属性节点
        //处理childNode参数 添加子节点
        if (typeof childNode === 'string') {
            createTextNode(node, childNode);
        } else if (childNode &#038;&#038; childNode.nodeName) {
            node.appendChild(childNode)
        } else if (childNode instanceof Array) {
            for (var i = 0; childNode[i]; i++) {
                node.appendChild(childNode[i])
            }
        }

        //处理文本节点
        if (textNode &#038;&#038; typeof textNode === 'string') {
            createTextNode(node, textNode);
        }
        return node;
    }
    var createAttributeNode = function(node, attrs) {
        for (var i in attrs) {
            //下面这种方式适用于原生的节点属性
            //node[i] = attrs[i];
            //在IE下setAttribute设置某些原生属性会有兼容性问题
            //node.setAttribute(i, attrs[i]);
            //document.createAttribute在IE下设置原生属性会不带引号
            var a = doc.createAttribute(i);
            a.value = attrs[i];
            node.setAttributeNode(a);
        }
    }
    var createTextNode = function (node, text) {
        node.appendChild(doc.createTextNode(text))
    }
} ();
</pre>
<p><b><a href="http://x1989.com/demos/nodecreator/source.html" target="_blank">Demo</a></b><br />
文档？足够的注释不需要文档！</p>
]]></content:encoded>
			<wfw:commentRss>http://x1989.com/a/407.html/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Javascript惰性函数函数的应用</title>
		<link>http://x1989.com/a/391.html</link>
		<comments>http://x1989.com/a/391.html#comments</comments>
		<pubDate>Mon, 18 Apr 2011 10:41:25 +0000</pubDate>
		<dc:creator>xhowhy</dc:creator>
				<category><![CDATA[Web开发]]></category>
		<category><![CDATA[前端开发]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[惰性函数]]></category>

		<guid isPermaLink="false">http://x1989.com/?p=391</guid>
		<description><![CDATA[function addEvent(element, type, func) {

	if (document.addEventListener)

		element.addEventListener(type, func);

<span class="readmore"><a href="http://x1989.com/a/391.html" title="Javascript惰性函数函数的应用">阅读全文——共633字</a></span>]]></description>
			<content:encoded><![CDATA[<pre lang="javascript">
function addEvent(element, type, func) {
	if (document.addEventListener)
		element.addEventListener(type, func);
	else
		element.attachEvent(type, func);
}
</pre>
<p>上面的函数在每次调用的时候都会检测document.addEventListener是否存在，并用它绑定一个事件，如果不存在，就使用ie的方式绑定事件。<br />
这个函数工作得很好，尽管它在浏览器的兼容性检测上还不够完善。但从性能的角度出发上，我们可以做得更好：只执行一次检测，就是在函数第一次被调用的时候。<br />
为了达到这个目的，我们使用一个javascript的惰性加载特性（http://peter.michaux.ca/articles/lazy-function-definition-pattern）</p>
<pre lang="javascript">
function addEvent(element, type, func) {
	if (document.addEventListener) {
		addEvent = function(element, type, func) {
			element.addEventListener(type, func)
		}
	}else{
		addEvent = function(element, type, func) {
			element.attachEvent(type, func)
		}
	}
	return addEvent(element, type, func)
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://x1989.com/a/391.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Kissy中jsonp api的bug</title>
		<link>http://x1989.com/a/387.html</link>
		<comments>http://x1989.com/a/387.html#comments</comments>
		<pubDate>Fri, 15 Apr 2011 11:56:57 +0000</pubDate>
		<dc:creator>xhowhy</dc:creator>
				<category><![CDATA[Web开发]]></category>
		<category><![CDATA[前端开发]]></category>
		<category><![CDATA[bug]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[jsonp]]></category>
		<category><![CDATA[Kissy]]></category>

		<guid isPermaLink="false">http://x1989.com/?p=387</guid>
		<description><![CDATA[在相邻的代码里多次调用Kissy的jsonp方法，调用十次大概会出现六次的：Uncaught ReferenceError: jsonp1302852733609 is not defined(anonymous function).同事仙羽查看源码发现，是kissy的jsonp api是调用太快了，产生了同一个时间戳。。两次请求返回的都是同个函数调用，但是kissy里面的jsonp有个垃圾收集的处理，结果把这个函数给删了，第二次再调用的时候就调用不到了。算是kissy的bug吧，应该用guid的。出错代码如下

<span class="readmore"><a href="http://x1989.com/a/387.html" title="Kissy中jsonp api的bug">阅读全文——共263字</a></span>]]></description>
			<content:encoded><![CDATA[<p>在相邻的代码里多次调用Kissy的jsonp方法，调用十次大概会出现六次的：Uncaught ReferenceError: jsonp1302852733609 is not defined(anonymous function).同事仙羽查看源码发现，是kissy的jsonp api是调用太快了，产生了同一个时间戳。。两次请求返回的都是同个函数调用，但是kissy里面的jsonp有个垃圾收集的处理，结果把这个函数给删了，第二次再调用的时候就调用不到了。算是kissy的bug吧，应该用guid的。出错代码如下</p>
<pre>
for(var i=0;i<10;i++){
    KISSY.jsonp('http://110.75.14.39/home/recommendTmallSpu.htm?appID=87&#038;num=4&#038;key=110202',function(data){
        console.log(data);
    })
}
</pre>
<p>问题就出现在ajax模块下的这行代码：</p>
<pre>
jsonp = c['jsonpCallback'] || JSONP + S.now();
</pre>
<p>贴一段jQuery源码中的实现：</p>
<pre>
// 默认的发起jsonp请求的设置 即url中callback=?的情况 回调函数也是"jsonp_"+时间错
jQuery.ajaxSetup({
	jsonp: "callback",
	jsonpCallback: function() {
		return jQuery.expando + "_" + ( jsc++ );
	}
});

// 装载jsonp的callback函数
jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {

	var dataIsString = ( typeof s.data === "string" );

	if ( s.dataTypes[ 0 ] === "jsonp" ||
		originalSettings.jsonpCallback ||
		originalSettings.jsonp != null ||
		s.jsonp !== false &#038;&#038; ( jsre.test( s.url ) ||
				dataIsString &#038;&#038; jsre.test( s.data ) ) ) {
                //响应容器
		var responseContainer,
			jsonpCallback = s.jsonpCallback =
				jQuery.isFunction( s.jsonpCallback ) ? s.jsonpCallback() : s.jsonpCallback,
			previous = window[ jsonpCallback ],
			url = s.url,
			data = s.data,
			replace = "$1" + jsonpCallback + "$2",
			cleanUp = function() {
				window[ jsonpCallback ] = previous;
				// 当有请求时调用callback
				if ( responseContainer &#038;&#038; jQuery.isFunction( previous ) ) {
					window[ jsonpCallback ]( responseContainer[ 0 ] );
				}
			};

		if ( s.jsonp !== false ) {
			url = url.replace( jsre, replace );
			if ( s.url === url ) {
				if ( dataIsString ) {
					data = data.replace( jsre, replace );
				}
				if ( s.data === data ) {
					// Add callback manually
					url += (/\?/.test( url ) ? "&#038;" : "?") + s.jsonp + "=" + jsonpCallback;
				}
			}
		}

		s.url = url;
		s.data = data;

		// 装载callback
		window[ jsonpCallback ] = function( response ) {
			responseContainer = [ response ];
		};

		// Install cleanUp function
		jqXHR.then( cleanUp, cleanUp );
</pre>
]]></content:encoded>
			<wfw:commentRss>http://x1989.com/a/387.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>通过设置p3p头来实现跨域设置cookie[转]</title>
		<link>http://x1989.com/a/385.html</link>
		<comments>http://x1989.com/a/385.html#comments</comments>
		<pubDate>Mon, 11 Apr 2011 07:29:13 +0000</pubDate>
		<dc:creator>xhowhy</dc:creator>
				<category><![CDATA[Web开发]]></category>
		<category><![CDATA[转载]]></category>
		<category><![CDATA[cookie]]></category>
		<category><![CDATA[p3p]]></category>

		<guid isPermaLink="false">http://x1989.com/?p=385</guid>
		<description><![CDATA[转自：http://huaidan.org/archives/1526.html

今天在w3网站上看到了一篇介绍p3p的文章（http://www.w3.org/TR/p3p/），利用这个可以实现跨域访问cookie，我也试验一下。

其实很简单：试验用了2个域名readlog.cn和diaor.com

<span class="readmore"><a href="http://x1989.com/a/385.html" title="通过设置p3p头来实现跨域设置cookie[转]">阅读全文——共878字</a></span>]]></description>
			<content:encoded><![CDATA[<p>转自：http://huaidan.org/archives/1526.html<br />
今天在w3网站上看到了一篇介绍p3p的文章（http://www.w3.org/TR/p3p/），利用这个可以实现跨域访问cookie，我也试验一下。</p>
<p>其实很简单：试验用了2个域名readlog.cn和diaor.com</p>
<p>首先在readlog.cn下放置一个文件setcookie.php 内容：<br />
PHP代码</p>
<p>header(’p3p: CP=”CAO DSP COR CUR ADM DEV TAI PSA PSD IVAi IVDi CONi TELo OTPi OUR DELi SAMi OTRi UNRi PUBi IND</p>
<p> PHY ONL UNI PUR FIN COM NAV INT DEM CNT STA POL HEA PRE GOV”’);//p3p<br />
setcookie(“Testcookie”,”test”,time()+3600,”/”,”.readlog.cn”);//设置cookie </p>
<p>再放置一个readcookie.php 内容：</p>
<p>然后在diaor.com下放置setcookie.php ，内容：<br />
JavaScript代码</p>
<p>1. &lt;script src=”http://www.readlog.cn/setcookie.php”&gt;&lt;/script&gt; </p>
<p>然后访问http://www.diaor.com/setcookie.php 抓取数据包可以发现，在readlog.cn域下生成了一个cookie ，名称是Testcookie,值是test</p>
<p>下面访问http://www.readlog.cn/readcookie.php 来验证一下，可以发现，cookie确实设置成功了。</p>
<p>有兴趣可以去掉header(’p3p: CP=”CAO DSP COR CUR ADM DEV TAI PSA PSD IVAi IVDi CONi TELo OTPi OUR DELi SAMi OTRi UNRi PUBi IN</p>
<p>D PHY ONL UNI PUR FIN COM NAV INT DEM CNT STA POL HEA PRE GOV”’);这句，试一下就会发现cookie能设置，但是在readlog.cn读不到这个cookie。</p>
]]></content:encoded>
			<wfw:commentRss>http://x1989.com/a/385.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>PHP Fatal Error重定向跳转</title>
		<link>http://x1989.com/a/362.html</link>
		<comments>http://x1989.com/a/362.html#comments</comments>
		<pubDate>Sat, 26 Mar 2011 06:57:51 +0000</pubDate>
		<dc:creator>xhowhy</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Web开发]]></category>
		<category><![CDATA[fatal error]]></category>
		<category><![CDATA[handler]]></category>
		<category><![CDATA[重定向]]></category>

		<guid isPermaLink="false">http://x1989.com/?p=362</guid>
		<description><![CDATA[在前端生产环境下，我们需要error_reporting(0)来禁止对用户输出任何错误信息；与此同时，如果能在不可预见地发生Fatal errors和Parse errors的时候跳转到其他页面，而不出现空白，那就能在一定程度上保证用户体验。

我们发现，PHP的error_handlers不能用来处理Fatal errors和Parse errors，于是就有了下面这个方法。

在php.ini文件中可以找到：

<span class="readmore"><a href="http://x1989.com/a/362.html" title="PHP Fatal Error重定向跳转">阅读全文——共525字</a></span>]]></description>
			<content:encoded><![CDATA[<p>在前端生产环境下，我们需要error_reporting(0)来禁止对用户输出任何错误信息；与此同时，如果能在不可预见地发生Fatal errors和Parse errors的时候跳转到其他页面，而不出现空白，那就能在一定程度上保证用户体验。<br />
我们发现，PHP的error_handlers不能用来处理Fatal errors和Parse errors，于是就有了下面这个方法。<br />
在php.ini文件中可以找到：</p>
<pre>
; String to output before an error message.
;error_prepend_string = "html code"
; String to output after an error message.
;error_append_string = "html code"
</pre>
<p>那么我们可以把error_prepend_string或者error_append_string前面的分号去掉，把它的值设置为”&lt;script&gt;window.location.href=&#8217;another_page.php&#8217;;&lt;/script&gt;”，在出错的时候使用javascript的redirect到另一个页面。<br />
但是这种做法似乎不太优雅…正在寻找通过服务器302临时重定向的方法。</p>
]]></content:encoded>
			<wfw:commentRss>http://x1989.com/a/362.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHP SPL File Browser</title>
		<link>http://x1989.com/a/359.html</link>
		<comments>http://x1989.com/a/359.html#comments</comments>
		<pubDate>Thu, 24 Mar 2011 12:44:11 +0000</pubDate>
		<dc:creator>xhowhy</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Web开发]]></category>
		<category><![CDATA[创新工厂]]></category>
		<category><![CDATA[Browser]]></category>
		<category><![CDATA[Directory]]></category>
		<category><![CDATA[File]]></category>
		<category><![CDATA[SPL]]></category>

		<guid isPermaLink="false">http://x1989.com/?p=359</guid>
		<description><![CDATA[俗话说不想偷懒的程序员不是好程序员。

所以为了向“好程序员”靠拢，我们要自觉地在工作中偷懒…当然不是要你偷工减料，而是要用程序员应该有的方式来“偷懒”，提高工作效率。

我所在的公司使用的PHP demo环境，出于安全方面的考虑，设置了禁止访问网站目录（列出目录文件列表），造成了我没有办法通过浏览器直接访问目录，查看到目录下的文件列表。上传了个php探针到demo服务器上，发现PHP的系列文件操作函数都被禁用了。这样我也没有办法写一段php脚本通过opendir、chdir、scandir等函数来遍历目录下的文件，输出文件列表到浏览器。

<span class="readmore"><a href="http://x1989.com/a/359.html" title="PHP SPL File Browser">阅读全文——共469字</a></span>]]></description>
			<content:encoded><![CDATA[<p>俗话说不想偷懒的程序员不是好程序员。<br />
所以为了向“好程序员”靠拢，我们要自觉地在工作中偷懒…当然不是要你偷工减料，而是要用程序员应该有的方式来“偷懒”，提高工作效率。<br />
我所在的公司使用的PHP demo环境，出于安全方面的考虑，设置了禁止访问网站目录（列出目录文件列表），造成了我没有办法通过浏览器直接访问目录，查看到目录下的文件列表。上传了个php探针到demo服务器上，发现PHP的系列文件操作函数都被禁用了。这样我也没有办法写一段php脚本通过opendir、chdir、scandir等函数来遍历目录下的文件，输出文件列表到浏览器。<br />
好在经过测试，发现并没有禁用PHP的SPL(SPL是Standard PHP Library的缩写)。这样我们就可以通过SPL中的DirectoryIterator来遍历目录了。<br />
于是就有了下面这个小工具，我想可以把它叫做PHP SPL File Browser或者PHP SPL Directory Browser。它强大得放在任意子目录下都可以浏览整站目录。代码写得很乱，就不献丑了，有需要的童鞋可以发Email给我。<br />
<a href="http://x1989.com/wp-content/uploads/2011/03/phpspldirectorybrowser.png"><img src="http://x1989.com/wp-content/uploads/2011/03/phpspldirectorybrowser-300x226.png" alt="" title="phpspldirectorybrowser" width="300" height="226" class="alignnone size-medium wp-image-382" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://x1989.com/a/359.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

