今天遇到一个cookie的问题: 名叫username的,域为www.umiwi.com的cookie无法删除,导致用户登录以后无法退出。搞了半天终于发现问题所在:原来是我关于cookie的基础知识没搞清楚
。。。。
Cookie不仅仅有名字和值两个属性,还有域(domain),过期时间(expires),路径(path)等属性。 其中,不同的域、不同的路径下可以存在同样名字的cookie。 比如这个页面: 用鼠标戳我
一般我们删除cookie的方法是用一个同样名字、过期时间为过去某个时候的Cookie覆盖之。 这时就一定要搞清楚你要删除的cookie的域和路径,Cookie域和路径要一样才能被覆盖。 否则产生的效果就是那个想要被删除的Cookie具有神奇的生命力,无法被清除~~~
另外,我发现在设置Cookie的时候,如果没有指定域名,那么设置的这个cookie的域默认为当前域,比如www.umiwi.com。 如果设置的时候指定了某个域,那么浏览器存的时候会自动在前面加.。比如PHP代码: setcookie('test','a',0,'www.umiwi.com'); 那么 浏览器里面存的Cookie的域为.www.umiwi.com。 所以,最好的方式是设置Cookie的时候怎么写的,删除的时候就怎么写。 要不就会出现我遇到的情况: 明明浏览器里看有 username=longbill,域为www.umiwi.com的Cookie,但是在php里写 setcookie('username','',time()-1000,'www.umiwi.com','/'); 无法删除那个Cookie。 原因就是我删Cookie的操作其实上是发了一个新的名叫username、值为空、过期时间为过去1000秒、域为.www.umiwi.com、路径为/的Cookie。这个Cookie发到浏览器马上就过期了,什么也看不到。而我要删除的在www.umiwi.com上的cookie还活的好好的。。。
补充一下HTTP的知识: php里面的header函数发送的header信息默认是不重复的,后面发的会自动覆盖前面的内容。一般说来HTTP请求的header部分也是没有重复信息的,除了Set-Cookie头! 所以,如果我们使用header函数来发送cookie,请注意加第二个参数true。 详见header函数。
完。
昨天不小心看到了Google Javascript Style Guide,Google在里面约定了一些名字的书写规则,也给出一些更好的建议。 下面我翻译一段个人认为很有价值的东西:
布尔表达式
以下代码在布尔表达式里都等于false:
-
null -
undefined -
''空字符串 -
0数字
但是请注意,以下这些等于true:
-
'0'字符串 -
[]空的数组 -
{}空的对象
这就意味着本来这样的代码:
while (x != null) {你可以这样来写(当你不希望x为0、空字符串、false时):
while (x) {当你希望检查一个字符串是否为空的时候你可以这样:
if (y != null && y != '') {但是这样会更简洁更高效:
if (y) {注意: 有很多容易搞错的布尔表达式(以下表达式的值都为true):
-
Boolean('0') == true/* Longbill注释:
'0' != true
* if ('0') alert('yes');
* if ('0' != true) alert('yes');
* if ('0' == false) alert('yes');
* 以上三个都会弹出yes!!
*/ -
0 != null
0 == []
0 == false -
Boolean(null) == false
null != true
null != false -
Boolean(undefined) == false
undefined != true
undefined != false -
Boolean([]) == true
[] != true
[] == false -
Boolean({}) == true
{} != true
{} != false -
Longbill 补充下:
NaN != true
NaN != false
Boolean(NaN) == false
三目运算符
这样的代码:
if (val != 0) {
return foo();
} else {
return bar();
}可以被简化成这样:
return val ? foo() : bar();三目运算符在生成html字符串的时候也很有用:
var html = '<input type="checkbox"' +
(isChecked ? ' checked' : '') +
(isEnabled ? '' : ' disabled') +
' name="foo">';&& 和 ||
由这两个逻辑运算符连接的表达式会从左到右依次执行,直到遇到满足条件为止。
所以"||" 又被称作 '缺省值' 操作符,因为如下代码:
/** @param {*=} opt_win */
function foo(opt_win) {
var win;
if (opt_win) {
win = opt_win;
} else {
win = window;
}
// ...
}可以被简写成:
/** @param {*=} opt_win */
function foo(opt_win) {
var win = opt_win || window;
// ...
}"&&" 同样很有用。比如,如下代码:
if (node) {
if (node.kids) {
if (node.kids[index]) {
foo(node.kids[index]);
}
}
}可以被简写成:
if (node && node.kids && node.kids[index]) {
foo(node.kids[index]);
}或者这样:
var kid = node && node.kids && node.kids[index];
if (kid) {
foo(kid);
}甚至可以这样:
node && node.kids && node.kids[index] && foo(node.kids[index]);
使用 join() 来创建字符串
一般来说,累加字符串是很常见的:
function listHtml(items) {
var html = '<div class="foo">';
for (var i = 0; i < items.length; ++i) {
if (i > 0) {
html += ', ';
}
html += itemHtml(items[i]);
}
html += '</div>';
return html;
}但是这种方式在万恶的IE浏览器下会很慢,通常以下代码会更快:
function listHtml(items) {
var html = [];
for (var i = 0; i < items.length; ++i) {
html[i] = itemHtml(items[i]);
}
return '<div class="foo">' + html.join(', ') + '</div>';
}注意:指定数组的下标来赋值会比直接用数组的push()方法更高效。
遍历Node List
在遍历Node list 的时候,常常会用到length属性来当循环的边界条件。因为循环的时间复杂度是O(n),而每循环一次,都要检查一下边界条件(length属性),这样时间复杂度变为O(n^2):
var paragraphs = document.getElementsByTagName('p');
for (var i = 0; i < paragraphs.length; i++) {
doSomething(paragraphs[i]);
}这样做会更高效(时间复杂度应该是O(n) ):
var paragraphs = document.getElementsByTagName('p');
for (var i = 0, paragraph; paragraph = paragraphs[i]; i++) {
doSomething(paragraph);
}以上这个方法同样适用于对象和数组(当数组不含有会被当成是false的值的时候)。
/* 原文出自:Google,翻译: Longbill (http://php.js.cn) 2010-10-19 */
另外,当你遍历一个Node的所有子Node的时候,可以用firstNode和nextSibling属性,就像这样:
var parentNode = document.getElementById('foo');
for (var child = parentNode.firstChild; child; child = child.nextSibling) {
doSomething(child);
}完。
记得08年flashplayer10刚出来的时候,我看到过一个视频 ,Adobe的人就是用Textmate开发的Flash。 他是用Flex SDK里面的mxmlc命令编译的。当年我还用Mac OS的Automation功能做了一个应用程序,功能是把AS文件拖动到上面就自动给你编译成swf文件。 今年再回头看的时候,发现其实有更简单的方法。那就是用TextMate的Actionscript3 Bundle。然后我就尝试去配置这个环境,结果发现还很不容易。 下面把我的过程跟大家分享一下:
- 当然你要有一台Mac
- 你得先安装 TextMate。
- 安装上面提到过的actionscript 3 bundle。
- 到http://www.adobe.com/cfusion/entitlement/index.cfm?e=flex3sdk 下载flex sdk
- 将sdk解压,放到一个方便找到的位置
- 然后打开Textmate->prefrences->advanced->shell variables,添加一个PATH变量,值是你的flex sdk里bin的位置,比如:/Developer/SDK/flex_sdk_3.5/bin。 如果已经存在PATH变量,那么请不要改动原来的数据,在原来数据的后面加冒号(:),然后再加上bin目录的位置。
- 同样是在Shell Variables里面,添加一个LC_ALL变量,值是en_US.UTF-8。因为我发现flex会根据系统语言来显示错误信息,但是显示出来的是乱码,所以还是统一用英文的错误信息算了
- 打开flex sdk的目录,进入frameworks,编辑flex-config.xml,把<target-player>9xxx</target-player>替换成<target-player>10.0.0</target-player>
然后就爽把,新建一个as文件,写一些东西,然后按苹果键+B,就会自动调用mxmlc编译你的as文件,生成swf。 当然actionscript3 bundle的功能还有很多,自己去发觉吧~
2010年10月18日更新
今天搞了一下flash player的debug版本。可以把as3程序trace出来的信息记录到一个文件。步骤大概是这样的:
- 新建一个文件 ~/mm.cfg ,写上TraceOutputFileEnable=1
- 打开textmate的 Bundles >> Bundle Editor >> Edit Commands
- 打开左边的ActionScript 3 这个Bundle,然后点击左下角的+按钮,选择New Command
- 然后在右边的详细信息区域做如下选择:Save:Nothing, Input: None, Output: Show as HTML, Activation: Key Equivalent (然后点击右边区域,再按Apple键+D),Scope Selector: source.actionscript.3
-
在Command(s)区域,写:
echo "<pre>" cat ~/Library/Preferences/Macromedia/Flash\ Player/Logs/flashlog.txt echo "</pre>"
好了,现在在as3的代码界面按Apple+D就可以看到刚刚运行的flash的trace信息了。 上图:

运行效果如下:

完。
最近在搞flash的东西。遇到一个事件冒泡带来的问题。类似Javascript,flash里面的元素也有事件冒泡机制。经常会遇到给一个外层的元素绑定一个mouse_over事件,本意是想实现进入这个外层的元素的时候触发。但是实现的时候却有很奇怪的表现:鼠标在这个元素内部移动的时候,遇到这个元素北部的元素的时候,内部元素触发mouse_over,这个事件会冒泡到外层这个元素,同样触发外层元素的mouse_over事件! 然后你就会发现,鼠标在这个外层元素内部移动的时候,绑定的事件会被触发很多次。
为了解决这个问题,JQuery自己实现了mouseenter和mouseleave事件,实现鼠标移入这个元素内部和离开这个元素的时候触发,鼠标在元素内部移动不会触发。原理我就不详细说了,大概是判断触发的对象与绑定事件的对象之间的关系吧。
在flash里面我自己实现了一个类似的东西,实现了mouseenter和mouseleave的响应。 大概原理是利用mouseover和mouseout的关系(在元素内部移动鼠标到内部的其他元素上的时候,会先触发mouseout,然后触发mouseover事件),把mouseout事件延后处理,然后看如果mouseover到了内部元素上,那就取消mouseout执行,否则触发mouseleave。呃。。。貌似很混乱。。。。核心思想就是利用setTimeout(function(){ },0); 把函数延后执行。
as代码:
function mouseEnterLeave(red,enterCall,leaveCall)
{
red.mouseOvering = false; //标记鼠标是否处在元素内部
red.addEventListener(MouseEvent.MOUSE_OVER,function(e:MouseEvent)
{
var ct = e.currentTarget;
try{ clearTimeout(ct.outTimer); }catch(e:Error){ }
if (!ct.mouseOvering) //如果从外面到里面,那么触发mouseEnter
{
enterCall.call(red);
}
ct.mouseOvering = true;
});
red.addEventListener(MouseEvent.MOUSE_OUT,function(e:MouseEvent)
{
var ct = e.currentTarget;
ct.outTimer = setTimeout(function()
{ //把mouseout响应延后执行,如果能执行,那么表示鼠标移出
ct.mouseOvering = false;
leaveCall.call(red);
},0);
});
}
当然,这个函数也可以在Javascript中实现。就像这样:(非IE)
function mouseEnterLeave(o,enterCallback,leaveCallback)
{
o.addEventListener('mouseover',function(e)
{
try{ clearTimeout(o.outTimer); } catch(e) { }
if (!o.overing)
{
if (typeof enterCallback == 'function') enterCallback.call(o);
}
o.overing = true;
},false);
o.addEventListener('mouseout',function(e)
{
o.outTimer = setTimeout(function()
{
o.overing = false;
if (typeof leaveCallback == 'function') leaveCallback.call(o);
},0);
},false);
}
Javascript的例子见这里(非IE浏览器)。
完。
前段时间手机不小心丢了。貌似是第一次主动丢手机(曾经有一次是被动丢的)。 后来就入手了一个Moto Droid。大概是5月下旬,当时淘宝上面均价3000左右。但是到处问都没货。。。没办法,后来花3300高价买了个。

因为Droid用是CDMA2000的3G制式,而且是verizon的无卡机,所以必须要到电信查询uim卡的五码,然后用软件写到手机里面。 拿到五码之后就马上开始写,按照淘宝JS的步骤一步步操作。结果最后一步教程上写做了,害的我用了整整一个通宵才搞定。。。不过写好之后就爽惨了~~
本人在四川成都,用的中国电信的3G卡,50元包了1GB的套餐。电信在成都的覆盖相当好,移动和联通的卡在学校寝室基本没什么信号,接电话都要到阳台,但是电信的在任何地方都是满格!手机上网网速也很快,平均200-300KB/s。紧急时候还可以用手机带电脑上网,感觉就像家里的2M宽带。 只是电信的客服差了点,不过也有好处,详见如何敲诈中国电信。
再说android系统。 我目前用的是android 2.2。Home程序是Launcher pro。常用的软件有:
- UCWeb: 上网
- Profiles : 情景模式快速切换
- aQQ: 一个第三方QQ客户端,感觉比官方的好点
- RockPlayer: 很猛的软件,实现了大部分视频格式的解码,包括rmvb等(乐phone的rmvb貌似是硬件解码)
- Twidroyd: 第三方Twitter客户端
- iDigu: 第三方嘀咕客户端(据说官方的快出来了)
- NewsRob: 第三方Google Reader阅读器,感觉不错,最常用
- Camera 360:国产照相软件。我觉得是android上最棒的照相程序了。
- PdaNet: USB连接电脑,可以让电脑通过手机上网
- TeslaLED: 把手机闪光灯当手电用,相当爽啊,毕竟是闪光灯,比普通手电筒夜晚照明效果好多了
- 本地通: 一个快速查找附近的餐馆/银行/酒店等的程序,可以显示目标在你的那个方向多远
- 条码扫描器、人人网客户端、豆瓣电台、Google Talk、Gmail、指南针等等。。。
其实最好用的还是android系统预装的各种Google应用。比如Gmail,设置好帐号后,就可以随时接收电子邮件。还有我最常用的Googe Talk,实现了24小时在线。 而且这些程序都是“同步”的概念,而不是简单的一个客户端。 也就是说你在电脑上和一个人聊天,如果手机也打开了这个聊天,那么电脑上聊的内容会自动显示到手机上,因为是同步的! 这样就不怕突然要外出而中断聊天了。
记得有次看了一篇E文,说Google这些实时同步程序用的是HTTP长连接来保持在线的。保持在线不需要发送数据,因此很省电,而且可以实现实时响应。 比起黑莓的什么Push Mail技术来说门槛低了很多。因为黑莓的push动作需要运营商支持,巨贵无比。而通过手机端http长连接方式来pull,既可以实现黑莓的实时邮件接收功能,又不需要运营商支持,只要可以上网就可以了。
在我看来android要比iOS好玩一些,自由度高一些。但是android上的游戏没iOS的好。绝大部分应用也都很一般。
其实我一直在找一个这样的软件: 手机如果丢了,可以通过别人的手机往我手机上发一个包含特定字符的短信,然后手机进入一个特定模式,自动打开GPS,把手机的方位信息发送到网上或者通过短信告知特定的手机。必要时候还可以锁死手机。那这样就不怕手机丢了。
完。
面试前端必须准备的一个问题:怎样去掉Javascript的Array的重复项。据我所知,百度、腾讯、盛大等都在面试里出过这个题目。 这个问题看起来简单,但是其实暗藏杀机。 考的不仅仅是实现这个功能,更能看出你对计算机程序执行的深入理解。
我总共想出了三种算法来实现这个目的:
-
Array.prototype.unique1 = function() { var n = []; //一个新的临时数组 for(var i = 0; i < this.length; i++) //遍历当前数组 { //如果当前数组的第i已经保存进了临时数组,那么跳过, //否则把当前项push到临时数组里面 if (n.indexOf(this[i]) == -1) n.push(this[i]); } return n; } -
Array.prototype.unique2 = function() { var n = {},r=[]; //n为hash表,r为临时数组 for(var i = 0; i < this.length; i++) //遍历当前数组 { if (!n[this[i]]) //如果hash表中没有当前项 { n[this[i]] = true; //存入hash表 r.push(this[i]); //把当前数组的当前项push到临时数组里面 } } return r; } -
Array.prototype.unique3 = function() { var n = [this[0]]; //结果数组 for(var i = 1; i < this.length; i++) //从第二项开始遍历 { //如果当前数组的第i项在当前数组中第一次出现的位置不是i, //那么表示第i项是重复的,忽略掉。否则存入结果数组 if (this.indexOf(this[i]) == i) n.push(this[i]); } return n; }
其中第1种和第3种方法都用到了数组的indexOf方法。此方法的目的是寻找存入参数在数组中第一次出现的位置。很显然,js引擎在实现这个方法的时候会遍历数组直到找到目标为止。所以此函数会浪费掉很多时间。 而第2中方法用的是hash表。把已经出现过的通过下标的形式存入一个object内。下标的引用要比用indexOf搜索数组快的多。
为了判断这三种方法的效率如何,我做了一个测试程序,生成一个10000长度的随机数组成的数组,然后分别用几个方法来测试执行时间。 结果表明第二种方法远远快于其他两种方法。 但是内存占用方面应该第二种方法比较多,因为多了一个hash表。这就是所谓的空间换时间。 就是这个测试页面,你也可以去看看。
2010年10月7日更新:
根据hpl大牛的思路,我写了第四种方法:
Array.prototype.unique4 = function()
{
this.sort();
var re=[this[0]];
for(var i = 1; i < this.length; i++)
{
if( this[i] !== re[re.length-1])
{
re.push(this[i]);
}
}
return re;
}
这个方法的思路是先把数组排序,然后比较相邻的两个值。 排序的时候用的JS原生的sort方法,JS引擎内部应该是用的快速排序吧。 最终测试的结果是此方法运行时间平均是第二种方法的三倍左右,不过比第一种和第三种方法快了不少。
完。
以前一直以为星相学和算命差不多是骗人的。但是随着阅人数量增加,逐渐发现星相学的一些结论的确很有实用性,尤其是在我发现两个生日相差两天的狮子座女生性格极其相似之后。
M是我的前女友,典型狮子座女生。 在我看来,她的特点就是很像“狮子”: 在外面看起来很奔放,女强人,事业心重;但是在家确温柔的像可怜的小猫(狮子其实也是猫),很黏人,很需要人疼。 这样的性格其实也挺可爱的,但是却存在隐藏的问题。
另外一个狮子座朋友Y比我大几岁。她最近刚失恋,具体原因不明。她很喜欢对方,但男方坚持要分,她很受伤。于是把精力全部用在工作上,像藉此忘掉不愉快的事情。但是我告诉她这样做是逃避,要正面她面临的问题,于是我们分析一通。我发现极有可能是对方在接触她到跟她恋爱之后发现她性格的很大差异,从而发现两个人不适合。没办法,狮子座就是这样的。
我觉得狮子座内与外的较大差异就是存在的隐藏的问题: 跟别人外在的接触的时候,别人认为你是这种性格; 但是恋爱之后,发现你却是那种性格。 这样很容易让双方都受伤。 Y曾跟我说过,她几乎排除掉所有星座了,也没发现适合她的。 我倒不这么认为: 首先人不可能凭借出生的时间就可以分成三六九等,各个星座的人都有各自的优缺点; 其次星相学只是基于大量统计得出的大概结论而已,不是每个人都合适。 再说了,不可能所有狮子座都没找到真爱吧? 肯定是有人很喜欢狮子座这种性格的。 (就像我喜欢受虐一样,总有人喜欢施虐 :) )
最后。。。。其实。。。。这篇日志主要目的是为Y征BF的,哈哈哈。 如果你觉得你很喜欢狮子座女生,可以联系我,我帮你介绍,
。对了,Y目前24岁左右,四川人,长得还不错,人品好,成电硕士,目前在成都腾讯当官。
呃。。最后。。。其实我想说,我很喜欢曾哥的歌,尤其是《狮子座》
呃。。。。其实我还想说,我也很喜欢春哥。。。
完。

