var addSheet = function(){ var doc,cssCode; if(arguments.length == 1){ doc = document; cssCode = arguments[0] }else if(arguments.length == 2){ doc = arguments[0]; cssCode = arguments[1]; }else{ alert("addSheet函数最多接受两个参数!"); } if(!+"\v1"){//增加自动转换透明度功能,用户只需输入W3C的透明样式,它会自动转换成IE的透明滤镜 var t = cssCode.match(/opacity:(\d?\.\d+);/); if(t!= null){ cssCode = cssCode.replace(t[0], "filter:alpha(opacity="+ parseFloat(t[1]) * 100+")") } } cssCode = cssCode + "\n";//增加末尾的换行符,方便在firebug下的查看。 var headElement = doc.getElementsByTagName("head")[0]; var styleElements = headElement.getElementsByTagName("style"); if(styleElements.length == 0){//如果不存在style元素则创建 if(doc.createStyleSheet){ //ie doc.createStyleSheet(); }else{ var tempStyleElement = doc.createElement('style');//w3c tempStyleElement.setAttribute("type", "text/css"); headElement.appendChild(tempStyleElement); } } var styleElement = styleElements[0]; var media = styleElement.getAttribute("media"); if(media != null && !/screen/.test(media.toLowerCase()) ){ styleElement.setAttribute("media","screen"); } if(styleElement.styleSheet){ //ie styleElement.styleSheet.cssText += cssCode; }else if(doc.getBoxObjectFor){ styleElement.innerHTML += cssCode;//火狐支持直接innerHTML添加样式表字串 }else{ styleElement.appendChild(doc.createTextNode(cssCode)) } }
有时我们需要在.js文件对文档动态引入一些CSS样式。对于一些短小的CSS代码来说,这好办,我们可以调用其style方法,如 1.var ddd = document.getElementById("ddd"); 2.ddd.style.border = "1px solid red"; 如果再长一点也无所谓: 1.var ddd = document.getElementById("ddd"); 2.ddd.style.cssText = "border:1px solid red;color:#000;background:#444;float:left"; 本人而言,我是喜欢后者。因为前者有严重的兼容问题。如float这个样式,在IE是styleFloat,在火狐等W3C标准游览器是cssFloat。而cssText则是通吃。 如果很长,我们可以动态导入一CSS文件。如function addSheetFile(path){ var fileref=document.createElement("link") fileref.rel = "stylesheet"; fileref.type = "text/css"; fileref.href = path; fileref.media="screen"; var headobj = document.getElementsByTagName('head')[0]; headobj.appendChild(fileref); }
这个函数在IE中有点累赘。我向来是支持哪个游览器就用哪个游览器的原生函数,直接使用二进制代码效率最高。 1.var oStylesheet = document.createStyleSheet ( sURL , iIndex ); createStyleSheet带的两个参数都是可选的。 但如果我们的样式是某个页面独有的,而且只有管理员才能使用到,而且那部分页面是动态生成的,我们需要一开始就引入它吗?需要特意弄个文件来装载它吗?最好的方法让这些样式与动态脚本捆绑在一起。我这个函数就为此而开发的。 坦白说,它最开始是为富文本编辑器而开发的。大家都知道,富文本输入框最流行的做法是把要输入的内容放到iframe中,这就涉及到两种document,一个主页面的document,另一个是iframe的document。 iframe的document又涉及到兼容问题。我们可以: 1. var iframe = document.createElement('iframe');//生成用于编辑的rich text editor 2. var iframeDocument = iframe.contentDocument || iframe.contentWindow.document; 3.…… 嘛,扯远了。总而言之,函数最开始的判定就是为这两种document而准备。如果没有涉及到iframe,我们只传入一个参数就行了。最后一个参数永远是CSS字符串。 然后是动态生成styleSheet元素,把CSS字符串加入到此元素的问题。当然如果有现阶段的,当然就用现成的。DOM元素越多对游览器的负担就越大。我们想到document.styleSheets方法。它返回一个集合,包含style元素与link元素,还涉及一兼容问题,如: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <meta http-equiv="content-type" content="text/html;charset=UTF-8" /> <%# 强制IE8像IE7一样呈现网页 -%> <meta http-equiv=”X-UA-Compatible” content=”IE=EmulateIE7″ /> <%#--默认所有的链接都在本窗口打开 -%> <base target="_self" /> <title><%= h(yield(:title)) || controller.action_name %></title> <%= stylesheet_link_tag "screen","button","style" %> <link rel="stylesheet" href="/stylesheets/print.css" type="text/css" media="print"> <!--[if lt IE 8]> <link rel="stylesheet" href="/stylesheets/ie.css" type="text/css" media="screen"> <![endif]--> <%= javascript_tag "window._token = '#{form_authenticity_token}'" if ActionController::Base.allow_forgery_protection %> <%= javascript_include_tag :defaults %> <style type="text/css" media="print"></style> </head> 上面用alert(document.styleSheets.length);测试一下,IE返回6,W3C游览器返回5。因此,否决了它。而且我们只用到style元素,不使用外联。第二部分的判定就针对head中的style元素而言,没有就创建一个。然后我们把CSS字符串加在第一个style元素就行了。 接着我们要加把保险锁,因为当media="print"时,只在页面打印时,定义的效果才有效。为了防止第一个style元素的media值不是screen,我们得改一改。 1.var styleElement = styleElements[0]; 2.var media = styleElement.getAttribute("media"); 3.if(media != null && !/screen/.test(media.toLowerCase()) ){ 4. styleElement.setAttribute("media", "screen"); 5.} 附上media的一些说明。 screen (缺省值),提交到计算机屏幕; print, 输出到打印机; projection,提交到投影机; aural,扬声器; braille,提交到凸字触觉感知设备; tty,电传打字机 (使用固定的字体); tv,电视机; all,所有输出设备。 最后是如此添加的问题。分IE,火狐与其他游览器三种。判定游览器也用各自的私有属性或方法。如styleSheet是IE独用的,getBoxObjectFor是火狐独用的(当然你也可以使用(/firefox/.test(navigator.userAgent.toLowerCase())),通常DOM操作是最耗时的,能用私有就用私有! 使用方法。addSheet("\ .RTE_iframe{width:600px;height:300px;}\ .RTE_toolbar{width:600px;}\ .color_result{width:2x;}\ .color_view{width:110px;height:25px;}\ .color_code{text-align:center;font-weight:700;color:blue;font-size:x;}\ div.table{width:176px;position:absolute;padding:1px;}\ div.table td{font-size:12px;color:red;text-align:center;}\ " );*/
最后追加几个相关的方法:var getClass = function(ele) { return ele.className.replace(/\s+/,' ').split(' '); }; var hasClass = function(ele,cls) { return ele.className.match(new RegExp('(\\s|^)'+cls+'(\\s|$)')); } var addClass = function(ele,cls) { if (!this.hasClass(ele,cls)) ele.className += " "+cls; } var removeClass = function(ele,cls) { if (hasClass(ele,cls)) { var reg = new RegExp('(\\s|^)'+cls+'(\\s|$)'); ele.className=ele.className.replace(reg,' '); } }
web重构技巧与常见问题的解决方法
一、 xhtml+CSS 技巧篇
●在重构也面之前要做的准备工作:
1.拿一张PSD效果图,必需是PSD的这样的话你就可以自己更加随意的做切片;
2.先把PSD不做切片生成一个网页,起名为index_psd.html(这个页面做参考用);
3. 在准备几个必需的文件夹 images(放图片) 、css(放css样式文件)、js(放js文件);
●准备工作做好以后,先分析整个页面的结构。分析页面的结构要先整体再部分,先看页面中最大的板块是怎样关联的是上下并列还是左右平铺。看清了页面的大板块结构,就可以构建页面最基础的几个区块了。例如我们的页面试上中下结构,这时就可以写:
<div id=”header”></div>//放也面头和导航等
<div id=”content”></div>//页面的主题内容
<div id=”footer”></div>//页面脚版权声明等等
●写css的时候就需要使用index_psd.html这个文件了,用DW打开这个文件,选择视图模式,可以通过拉辅助线,来测量各个区块的长宽为设置CSS提供参考,这样做的好处就是重构出来的页面可以精确到1像素。
●每写好一个区块就要用IE和ff测试下效果,以便及时发现问题及时解决,在各个区块没内容的时候最好给他们都加上背景色。
●写好大的板块后,再分析大板块里面的内容,同样的道理也是先整体再部分,例如内容页面看起来是左右两个板块,这个时候我们可以把代码写为:
<div id=”header”></div>//放也面头和导航等
<div id=”content”>//页面的主题内容
<div class=”content-2-1”></div>//左边
<div class=”content-2-2”></div>//右边
</div>
<div id=”footer”></div>//页面脚版权声明等等
其中content-2-1中的2表是分两栏,2-1表示左栏,2-2表示右栏这样的分栏方式可以使自己查看页面代码的时候更加直观,分好多栏的时候这个优势更加明显。
●新闻列表,文章列表等等最好使用:
<ul>
<li>新闻标题1</li>
<li>新闻标题2</li>
…………
<li>新闻标题n</li>
</ul>
●栏目列表加描述的最好用:
<dl>
<dt>栏目1</dt>
<dl>栏目1描述</dl>
<dt>栏目2</dt>
<dl>栏目2描述</dl>
</dl>
●在CSS文件定义的最开始最好加上如下语句
body,html{ height:100%; }
*{ margin:0px; padding:0px; }
●最好能给大的区块设置overflow::hidden,这样可以保证容器不被撑开,从而破坏整个页面的布局。
二、 DIV+CSS 问题篇
1. IE6意外空白问题:
在并列的几个小区块横铺在一个大区块中的时候,本来小区块宽度的和等于大区块的宽度,在FF等其他浏览器中没问题,可是在IE6中就是有一个区块显 示不出来要不就被挤到下面去了。这个时候可以设置小区块的css 为display:inline。如果这个办法还不行那就把各个区块的宽度减少1到2个像素。
2.IE6重影问题:
有时在IE6中在一个大DIV结束的底端老出现div内容结尾几个字符的重复,在FF等其他浏览器里面就不会出现。解决这个问题有两个办法:1)删除注 释;2)在这个DIV的后面填加<div class=”clear”></div> 定义clear的CSS样式为:
.clear {
font-size: 1px;
clear: both;
visibility: hidden;
width: 1px;
}。推荐使用第二种方法,如果把注释去掉的话代码的可读性就受到影响了。
3.IE6无法居中的问题:
一般情况下只要给一个div(设其id为1)设置css样式:margin:0px auto;就可以让这个div在盛放它的容器(设其id为0)中居中了,它们的结构如下:
<div id=”0”>
<div id=”1”> … </div>
</div>
但是IE6就不行。这个时候可以给div0的css设置:text-align: center;
4. IE6有链接的图片有意外边框出现
在IE6中有时有链接的图片会有一个难看的边框出现,这个是由<a>引起的,这个时候可以设置通过在CSS中设置a { border:0px;}来消除。
5.FF中DIV里面的内容出轨
有时在IE中看很正常的内容在FF中却看到DIV里面的东西跑到外面了,这种情况在div有边框的时候尤为明显。这是因为div在IE中设置了高度后,如 果div里面的内容如果高于div的时候,div会自动增高。但是FF就没有这么灵活,只要限定了高度就不会自己改变。这时可以通过重设高度来解决这个问 题,也可以把高度设为自动。
6.FF中区域意外消失
在IE中很正常的布局在FF中却有一个区域消失了,这个问题在页面的最下角版权区块经常出现。这个时候可以通过给这个区域添加:clear:both;来解决。
其他的问题暂时想不起来了,在重构的过程中总会有一些莫名奇妙的问题,只要善于思考,不厌其烦的测试,或是到网上查找,总会找到解决办法的。每一个问题的解决都是一个不小的收获。
电脑族缓解眼疲劳的10个快速方法
电脑眼病的一些常见症状:
•头痛
•疲惫、发痒、干涩或流眼泪
•视力模糊
•脖子、后背或肩膀酸痛
•对光敏感
大多数人都熟悉这些症状,因为现今社会人们不断发现自己每天大多数时间都和电脑度过。在数字时代,以前与人的生活紧密相连的是手机等手持装置,而现在则是类似微型电脑的东西,这就是电脑眼病更加频繁的原因。
如果你发现自己患有上述任何症状,以下是一些快速缓解的方法:
1.眨眼睛
眨眼很重要,因为它可以给眼睛提供水分以防止眼睛发痒或干涩。当你的视力集中于电脑屏幕时,无论是看电子表格或玩在线游戏,你很可能根本不眨眼睛。视力离开屏幕后尽量不要眨眼睛
2.调节室内光线
确保在光线充足的房间使用电脑,注意, “光线充足”并不是指光线刺眼。光线过亮也会引起眼疲劳,特别是透过窗子的自然光。用遮光帘或窗帘来遮挡部分阳光,并使用荧光灯或低瓦数的灯泡或灯管。舒适的光线对预防眼疲劳很必要,还有助于减压。
3.调整电脑亮度和对比度
进入电脑显示设置,做些必要的调整以配合房间的亮度。你还需调整字体和背景的对比度,这样面对显示器你就不会眯眼。还要调整字体大小和颜色,给眼睛一些休息,你在电脑上的阅读时眼睛不会很难受。
4.自己也要休息
不要很长时间盯着电脑看,也不要几个小时坐着一动不动。如果你不能挤出15分钟的休息时间来离开办公桌和电脑屏幕,也要稍事休息,站起来,伸展一下筋骨。要让眼睛放松,使血液循环尽可能顺畅,以防止眼睛疲劳和肌肉僵硬。离开电脑屏幕,做一些办公室运动
5.移动显示器
如果你的电脑屏幕是局限于一个狭小空间的角落里,要考虑将其移动。当你的视线离开屏幕,想让眼睛休息,并不想盯着海报、墙壁或杂乱的东西时,试着将显示器移到一个你的目光离开显示器可以遥望的区域
6.消除眩光
来自电脑屏幕、墙壁、窗户或任何反光表面的眩光都会导致眼睛疲劳。如果可能的话,对显示器安装防眩光屏幕,尽可能遮盖反光源。如果还没准备好,你应该拉下百叶窗或窗帘,尽量减少室外阳光照射下所造成的任何问题。
7.做眼保健操
几个简单的眼保健操动作可以预防或减轻眼睛疲劳:
•盯着远处的一个东西,看几分钟。
•将手掌搓热,闭上眼睛,然后捂住眼睛。想象着盯着远处的东西,同时做深呼吸。睁开眼睛,手放开。重复上述步骤,至少做三次。
•闭上眼睛,晃动脖子、头部及肩膀使眼睛得到放松,以减少任何肩部疼痛。
8.给眼睛溅些水
如果你觉得眼睛有灼烧感,那么上卫生间给眼睛溅些少许冷水。水慢慢干后再回办公室。
9.面部按摩
弄湿毛巾或纸巾上蘸些温水,轻轻擦脸、额头和脖子。持续按摩这些区域,不要揉到眼睛。这可以刺激眼睛周围的神经,有助于缓解盯着电脑屏幕造成的疲劳。
10.看眼科医生
如果任何眼睛疲劳的症状持续,就要看看医生。眼科检查可以确定是否有任何需要治疗的严重疾病。最糟糕的是你可能忽视了由于长时间使用电脑而造成的严重身体状况问题。
(转)20个头脑训练方案
来自:《我的生活巨变》 杰夫•尼克尔斯
为了保持敏锐,锻炼我们的大脑是很重要的。我们思考得越少,它就会变得越迟钝,以下是20个头脑训练的方案。
1)读一本好书
读书会激发想象力,让你的头脑开始工作,我喜欢让书本带着我走,我总是有一本有时甚至三至四本书在读!大部分书我是从图书馆里借来的,这样就不用花钱买每一本书了,这也使我能够毫无风险地广泛阅读各种书籍。
2)大脑学院
视频游戏不好的一面是导致脑袋腐烂,但实际上有些也会帮助你增强思维,我喜欢大脑学院游戏,这是一款用头脑玩笑测试头脑敏锐性的合集。(Big Brain Academy for the Will,这是原文中的游戏名称,是一个Will下的游戏智力游戏,很不错的。)
3)练习冥想
不要担心,我不是要在这里离开新时代的最前端,冥想的方式有很多种,对我而言,冥想就是花一点时间独处达到放松和集中思考的方式,它是神奇的治疗。
4)获得大量的休息
缺少睡眠能够影响你吸收新信息的能力,这意味着大学里通宵达旦补习的效率比你想象的要低得多,你的大脑需要休息,这可能是为什么事情总是在睡了好觉后变得更加清晰明朗。
5)规律地锻炼
你难道想没一会就从跑步机上下来吗?运动通过改善血液到大脑的流动从而改善大脑功能,一份研究发现体育锻炼实际上能帮助扩大大脑的体积,所以,如果你想要一个更大、更好的大脑,那么就去运动吧!
6)吃一顿好早餐
这不是不切实际,吃一顿好早餐确实令你有个更好的开始,你应该吃高蛋白和优质碳水化合物的的早餐,两片夹着花生牛油的全麦吐司就符合这一条了,鸡蛋同样是蛋白质的好来源,坚果、牛奶和新鲜水果都能为大脑提供良好的营养。
7)积极地思考
鼓励自己,我相信积极思考会提供大脑效能和帮助避免失望,我想说你的大脑就像电脑一样,垃圾进来、垃圾出去。发现积极,做所有能够使你感觉良好的事情,这些事情将会帮助你的精神变得更有生产力。
8)不断地学习
不要停止怀疑你的世界,寻找新的体验、技能和知识,开始去做你感兴趣做的事情。一份著名的研究表明伦敦出租车司机大脑的确定领域比一般的市民得到更大的开发,这是由于他们需要学习如何在迷宫般的城市街道上导航,我们能够运用此项挑战我们大脑的技术来增进我们的能力。
9)戒酒
酒精是抑郁的原因,它降低精神功能,酒能乱性是有充分证据的,如果你想要有顶尖的精神表现,那么停止喝酒吧,另外它也减弱人的睡眠,阻碍你清晰思考的能力。
10)拥有浪漫(特别是女性)
11)打破你的例程
选择一条新路开车去工作,试着用另外一只手去写字,将一点不同的东西掺杂在一起,这将振作你的大脑因为它需要你思考更多。你不能只是自动驾驶,离开你的定式来挑战你的大脑,它将有所反应,这是使你脑浆流动的好方法。
12)不要看太多电视
研究者发现在1-3岁时看太多电视会导致儿童注意力方面出问题,电视使心态麻木,从沙发上起来并离开电视机。当然,也有一些好的教育节目给孩子和大人们,但是整体上美国人看太多电视了,如果你想要高效的精神表现就关掉电视吧。
13)处理数字问题
心算而不是用计算器计算,我们已经变得精神懒惰了,我们依赖工具而不是自己思考,处理和记忆数字是使大脑恢复状态的好途径。
14)停止依靠GPS走路
记住第8条里所讲的出租车司机,用你的大脑去指出如何从点A到点B是很好的思维体操,你必须用你大脑的能力来决定空间关系来提高读地图的效率和穿梭城市,在一个陌生的地方旅行就更好了!
15)唤起远久的记忆
找出老照片并且开始翻阅,这将进入你头脑中的记忆银行,图像将帮助你想起你已经忘记的东西,深入挖掘所有你记得的东西。如果你有别的方法来唤醒你的记忆,就像以前的信件和家庭电影,那么也尽可能得利用它们。
16)创造优美的音乐
学习演奏一件乐器是超级棒改变你的大脑的方法,它需要你大脑的多个不同部分协调工作来创作出你想要的旋律。当然,如果你已经是一个音乐家了,迫使你自己学习新技术。音乐是思想伟大的锻炼。
17)说一种新语言
许多人同意学习一门新语言是使思想延伸的一种有力途径,如果你曾经尝试学习即使是几个新单词,那么你知道这会很难。当然,给大脑越难的东西越好!你有比你想象的要多得多的思维能力,让它试一下吧!
18)记忆一首歌
我们头脑中都储存有许多老歌,但为什么不通过学习一些新的调子来扩充我们的记忆?它将在开始的时候花费一点时间,但如果你坚持怎么做,你将发现会越来越简单,这是你的大脑恢复状态了。
19)遮住你的双眼绕你的屋子走
这看起来是一种陌生的活动,但你的大脑能够处理它,一旦你试了几次,你就能发现它很有趣很有挑战性。另外,这会应用你的记忆、运动技能和推理能力,多么好的锻炼!
20)扩大你的词汇量
决定每天学习一个新单词,有许多能够帮你做这项努力的网站,你将不止扩大了你的思想,而且当你在谈话中引入一个新词汇时能够使你的朋友和同事印象深刻。
Linux下跑Windows程序之PlayOnLinux
今天基于Wine的软件PlayOnLinux集成了部分Windows程序的安装卸载,初步感受还不错,特记录如下:
首先 从 http://www.playonlinux.com/en/ 选择适合你的安装方式
本人采用Ubuntu For Maverick version的方式:
wget -q “http://deb.playonlinux.com/public.gpg” -O – | sudo apt-key add –
sudo wget http://deb.playonlinux.com/playonlinux_maverick.list -O /etc/apt/sources.list.d/playonlinux.list
sudo apt-get update
sudo apt-get install playonlinux
如果是首次启动PlayOnLinux必须联网,会自动进行一些必要的备置。
然后联网选择安装需要的Windows程序。
最后就可以脱机从PlayOnLinux上启动已经安装的Windows程序。
如果你需要安装的Windows软件不在PlayOnLinux软件库中,而你又想试试其在Linux中是否能跑,那你自己自行安装Wine这个Windows兼容层。
1)安装wine最新版本Wine1.3*
从官网 http://www.winehq.org/ 选择合适自己安装方式
本人Ubuntu采用的具体过程:
sudo apt-get remove wine
sudo add-apt-repository ppa:ubuntu-wine/ppa
sudo apt-get update
sudo apt-get install wine1.3
2)安装.net2.0 (可能不是必须的但建议安装)
自行到网上搜索下载.net2.0安装包
然后在shell中执行:wine control 调出Wine的控制面板,点击添加安装程序,本地浏览选择安装 .net2.0 (文件类型过滤一定要选择所有文件)
3)安装你的目标Windows程序
和第2)步类似
IE假死-在地址栏输入URL地址弹出新窗口的解决方法
症状1:IE输入URL地址,弹出新窗口打开。无论什么情况,有时会弹出两个窗口,一个空白页和一个目标页。
症状2:当pc中装有世界之窗或者傲游时又设置IE为默认浏览器,点击MSN中的链接会弹出两个窗口,并且立即无响应和死机。
症状2:当pc中装有世界之窗或者傲游时,在ie中输入地址会跳转到世界之窗或傲游,而且不管是不是设置他们为默认浏览器。
常见描述:没有打开Theworld或者Maxthon,只打开IE时,输入URL地址、选择地址栏下拉框的地址或者在收藏夹中选择地址,均会弹出一个新的IE窗口,在新窗口中打开此URL,并且巨慢,似乎IE失去了响应。
若开了Maxthon或者Theworld类可以截获IE新地址请求的外壳,再打开新的IE窗口,重复上述打开地址操作,会在Maxthon或者Theworld中新打开一个页面,速度正常。
原因:只是猜测,因为多个浏览器安装后的冲突,或者是IE7补丁安装的缘故。多出现在安装了绿色IE7或者是IE selecter后。
解决方法:
删掉 HKEY_CLASSES_ROOT / CLSID / {C90250F3-4D7D-4991-9B69-A5C5BC1C2AE6}
或者
卸载Internet Explorer for Windows XP Service Pack 2(KB905915)补丁
赛格威原理分析
国外一群学生DIY http://web.mit.edu/first/segway/
站在车上的驾驶人与车辆的总体重心纵轴作为参考线。当这条轴往前倾斜时,赛格威车身内的内置电动马达会产生往前的力量,一方面平衡人与车往前倾倒的扭矩,一方面产生让车辆前进的加速度,相反的,当陀螺仪发现驾驶人的重心往后倾时,也会产生向后的力量达到平衡效果。因此,驾驶人只要改变自己身体的角度往前或往后倾,赛格威就会根据倾斜的方向前进或后退,而速度则与驾驶人身体倾斜的程度呈正比。
赛格威HT装有五个陀螺仪传感器,事实上只需三个传感器就可完成探测前、后方向的倾斜度外加侧倾程度(即“转向”)。多出的传感器是为增加冗余性,确保车辆更加可靠。此外,赛格威有两个倾斜传感器,内部充满电解液。就像你的内耳一样,该系统可以根据液体表面的倾斜判断自身与地面的相对位置。
javascript高效简洁代码的编写及优化技巧
http://www.js8.in/350.html
前言
随着互联网前端技术的革新,javascript越 来越重要,并且js的轻便,非严格的写法,使越来越多的人掌握了js,可是谈到js的写法,很多人都觉得自己很熟悉,很了解,但是笔者在实践中发现js并 非大家想象的那么简单,就像同事一句话:php会的很多,一抓一大把,而真正会js的却不多。仔细想想,原因很简单,js的加载到客户端运行的,不像 php可以一个include就可以搞定,而且引入的文件中不用的函数可以放着不动,而js不同,如果加入很多很多无用的函数会大大的占有带宽,不利于用 户体验。下面结合笔者实际开发过程中遇到的问题,以及自己收集的技巧,谈谈js高效简洁代码的编写及其优化的技巧。当然网上也有很多类似的文章,不过建议 大家还是不要人云亦云,真正适合自己的技巧跟编写习惯才是最好的!
真假的判断
Javascript中有null、undefined、string、number、boolean五种基本的类型,一般判断真假或者为空的时候大家会使用下面的代码:
if(a==true){ //doSomeTing(); }
但是这种方法很不简洁,我们完全可以使用1,0来判断,比如我们设定一个a,如果a为假,我们就改成真,而a在程序后面可能用于判断,最简单也是最好理解的方法就是下面的写法
var a=false; if(a==false){ a=true; }
既然提到了0,1,肯定有人想到了第二种写法:
var a=0; if(!a){ a=1; }
这个代码还可以进一步简写优化,就是使用js的三元运算符,也就是三目运算符:
var a=0; !a?a=1?null;
还有一点,对于空字符串的判断,往往采用if(a==””),其实对于空字符本身就是false,下面我总结了下Javascript中的真假值,希望对大家有用
JavaScript 中的真假值
类型 真假值
Null 总是为假(false)
Undefined 总是为假(false)
Boolean 保持真假值不变
Number +0,-0 或是 NaN 的时候为假,其它值为真
String 空字符串的时候为假,其它值为真
Object 总是为真(true)
数组跟对象的定义
对于类似下面的正统数组跟对象的定义
var a=new Array; var b=new obj; obj.name="WYQ"; obj.webSite="http://www.js8.in";
我们可以使用
var a=[]; var b={name:"WYQ",webSite:"http://www.js8.in"};
来代替
循环的控制
在使用循环遍历时候要注意提前把长度或者要计算的长度记录下来,如下面的写法
var list = document.getElementsByTagName('p'); for (var i = 0, l = list.length; i < l; i++) {//注意此处把list的长度提前计算出来,避免了每次循环重复计算 …… }
注意循环体内部的写法,该放在外面的放在外面如下面的代码
var list = $(".abc"); for (var i = 0, l = list.length; i < l; i++) {//注意此处把list的长度提前计算出来,避免了每次循环重复计算 var a=list[i].html(); $("#abc").after(a); }
我们分析一下:每次循环的时候,都要首先解析$(”#abc”);势必效率变低,接着在使用after插入到#abc中去。这样子写效率会很低的,而下面的写法就高效了
var list = $(".abc"); var b = $("#abc"); for (var i = 0, l = list.length; i < l; i++) {//注意此处把list的长度提前计算出来,避免了每次循环重复计算 var a=list[i].html(); b.after(a); }
这样的写法还不是最高效的,看下面的方法
var list = $(".abc"); var b = ""; for (var i = 0, l = list.length; i < l; i++) {//注意此处把list的长度提前计算出来,避免了每次循环重复计算 b+=list[i].html(); } $("#abc").after(b);
看似简单的Javascript代码,其实要做的功夫很多!
用while还是for?
对于我来说,那个使用的方便,那个用的变量少使用那个,如对顺序没有关系的循环可以使用while,如下面的两段代码,前者使用了for,后者使用了while,两者明显while使用的变量少,虽然for容易使大家理解
//使用for var arr = [1,2,3,4,5,6,7]; var sum = 0; for (var i = 0, l = arr.length; i < l; i++) { sum += arr[i]; } //使用while var arr = [1,2,3,4,5,6,7]; var sum = 0, l = arr.length; while (l--) { sum += arr[l]; }
条件判断的优化技巧
1、对于可能性的排列按照从高到底的顺序进行排列
原因很简单,可以减少程序的试探次数。
2、使用三目运算符三目运算符比if else判断语句效率高,而且往往代码比较简洁如下面的两段代码
//使用if else if (a > b) { num = a; } else { num = b; } //三目运算符 num = a > b ? a : b; //谁说三目不能代替if else的function? c=a>b?function(){ }:function(){ }; c();
使用switch 代替if对于同一个条件不同情况的判断,使用switch简洁易懂,并且switch本身比if效率要高,在IE下尤为明显!
==与===的区别
看过jQuery源码的朋友发现,其中很多使用的是===,而不是==,这是因为===的效率比==要高,但是使用===要注意,===不会进行类型的转换,比如如果你确定比较两者类型相同,推荐使用===,这也是大家在编写代码时候自己细节的养成。当然也有一定的注意情况,下面仔细的说说==跟===的区别
=== 操作符的判断算法
在使用 === 来判断两个值是否相等的时候,如判断x===y,会首先比较两个值的类型是否相等,如果不相等的话,直接返回 false 。接着根据 x 的类型有不同的判断逻辑。
如果 x 的类型是 Undefined 或 Null,则返回 true 。
如果 x 的类型是 Number,只要 x 或 y 中有一个值为 NaN,就返回 false ;如果 x 和 y 的数字值相等,就返回 true ;如果 x 或 y 中有一个是 +0,另外一个是 -0,则返回 true 。
如果 x 的类型是 String,当 x 和 y 的字符序列完全相同时返回 true,否则返回 false 。
如果 x 的类型是 Boolean,当 x 和 y 同为 true 或 false 时返回 true,否则返回 false 。
当 x 和 y 引用相同的对象时返回 true,否则返回 false 。
== 操作符的判断算法在使用 == 来判断两个值是否相等的时候,如判断x==y,当 x 和 y 的类型一样的时候,判断逻辑与 === 一样;如果 x 和 y 的类型不一样,== 不是简单的返回 false,而是会做一定的类型转换。
如果 x 和 y 中有一个是 null,另外一个是 undefined 的话,返回 true 。如null == undefined。
如果 x 和 y 中一个的类型是 String,另外一个的类型是 Number 的话,会将 String 类型的值转换成 Number 来比较。如3 == “3″。
如果 x 和 y 中一个的类型是 Boolean 的话,会将 Boolean 类型的值转换成 Number 来比较。如true == 1、true == “1″
如果 x 和 y 中一个的类型是 String 或 Number,另外一个的类型是 Object 的话,会将 Object 类型的值转换成基本类型来比较。如[3,4] == “3,4″
需要注意的是 == 操作符不一定是传递的,即从A == B, B == C并不能一定得出A == C。考虑下面的例子,var str1 = new String(”Hello”); var str2 = new String(”Hello”); str1 == “Hello”; str2 == “Hello”,但是str1 != str2。
typeof使用时候注意
对于同一个var a=”abc”;
在FF下typeof a==string 返回 true
在IE下返回false,IE就是这样的娇贵!
推荐写法:
typeof a==”string”
最后,尽量避免使用eval等语句!
eval、Function、execScript等语句会再次使用javascript解析引擎进行解析,需要消耗大量的执行时间。
P.S.此文章不断整理更新中,有好的想法,大家可以提出来讨论
Redis几个认识误区
前几天微博发生了一起大的系统故障, 很多技术的朋友都比较关心,其中的原因不会超出James Hamilton在On Designing and Deploying Internet-Scale Service(1)概括的那几个范围,James第一条经验“Design for failure”是所有互联网架构成功的一个关键。互联网系统的工程理论其实非常简单,James paper中内容几乎称不上理论,而是多条实践经验分享,每个公司对这些经验的理解及执行力决定了架构成败。
题外话说完,最近又研究了Redis。去年曾做过一个MemcacheDB, Tokyo Tyrant, Redis performance test, 到目前为止,这个benchmark结果依然有效。这1年我们经历了很多眼花缭乱的key value存储产品的诱惑,从Cassandra的淡出(Twitter暂停在主业务使用)到HBase的兴起(Facebook新的邮箱业务选用 HBase(2)),当再回头再去看Redis,发现这个只有1万多行源代码的程序充满了神奇及大量未经挖掘的特性。Redis性能惊人,国内前十大网站 的子产品估计用1台Redis就可以满足存储及Cache的需求。除了性能印象之外,业界其实普遍对Redis的认识存在一定误区。本文提出一些观点供大 家探讨。
1. Redis是什么
这个问题的结果影响了我们怎么用Redis。如果你认为Redis是一个key value store, 那可能会用它来代替MySQL;如果认为它是一个可以持久化的cache, 可能只是它保存一些频繁访问的临时数据。Redis是REmote DIctionary Server的缩写,在Redis在官方网站的的副标题是A persistent key-value database with built-in net interface written in ANSI-C for Posix systems,这个定义偏向key value store。还有一些看法则认为Redis是一个memory database,因为它的高性能都是基于内存操作的基础。另外一些人则认为Redis是一个data structure server,因为Redis支持复杂的数据特性,比如List, Set等。对Redis的作用的不同解读决定了你对Redis的使用方式。
互联网数据目前基本使用两种方式来存储,关系数据库或者key value。但是这些互联网业务本身并不属于这两种数据类型,比如用户在社会化平台中的关系,它是一个list,如果要用关系数据库存储就需要转换成一种 多行记录的形式,这种形式存在很多冗余数据,每一行需要存储一些重复信息。如果用key value存储则修改和删除比较麻烦,需要将全部数据读出再写入。Redis在内存中设计了各种数据类型,让业务能够高速原子的访问这些数据结构,并且不 需要关心持久存储的问题,从架构上解决了前面两种存储需要走一些弯路的问题。
2. Redis不可能比Memcache快
很多开发者都认为Redis不可能比Memcached快,Memcached完全基于内存,而Redis具有持久化保存特性,即使是异步 的,Redis也不可能比Memcached快。但是测试结果基本是Redis占绝对优势。一直在思考这个原因,目前想到的原因有这几方面。
- Libevent。和 Memcached不同,Redis并没有选择libevent。Libevent为了迎合通用性造成代码庞大(目前Redis代码还不到 libevent的1/3)及牺牲了在特定平台的不少性能。Redis用libevent中两个文件修改实现了自己的epoll event loop(4)。业界不少开发者也建议Redis使用另外一个libevent高性能替代libev,但是作者还是坚持Redis应该小巧并去依赖的思 路。一个印象深刻的细节是编译Redis之前并不需要执行./configure。
- CAS问题。CAS是Memcached中比较方便的一种防止竞争修改资源的方法。CAS实现需要为每个cache key设置一个隐藏的cas token,cas相当value版本号,每次set会token需要递增,因此带来CPU和内存的双重开销,虽然这些开销很小,但是到单机10G+ cache以及QPS上万之后这些开销就会给双方相对带来一些细微性能差别(5)。
3. 单台Redis的存放数据必须比物理内存小
Redis的数据全部放在内存带来了高速的性能,但是也带来一些不合理之处。比如一个中型网站有100万注册用户,如果这些资料要用Redis来存 储,内存的容量必须能够容纳这100万用户。但是业务实际情况是100万用户只有5万活跃用户,1周来访问过1次的也只有15万用户,因此全部100万用 户的数据都放在内存有不合理之处,RAM需要为冷数据买单。
这跟操作系统非常相似,操作系统所有应用访问的数据都在内存,但是如果物理内存容纳不下新的数据,操作系统会智能将部分长期没有访问的数据交换到磁盘,为新的应用留出空间。现代操作系统给应用提供的并不是物理内存,而是虚拟内存(Virtual Memory)的概念。
基于相同的考虑,Redis 2.0也增加了VM特性。让Redis数据容量突破了物理内存的限制。并实现了数据冷热分离。
4. Redis的VM实现是重复造轮子
Redis的VM依照之前的epoll实现思路依旧是自己实现。但是在前面操作系统的介绍提到OS也可以自动帮程序实现冷热数据分离,Redis只 需要OS申请一块大内存,OS会自动将热数据放入物理内存,冷数据交换到硬盘,另外一个知名的“理解了现代操作系统(3)”的Varnish就是这样实 现,也取得了非常成功的效果。
作者antirez在解释为什么要自己实现VM中提到几个原因(6)。主要OS的VM换入换出是基于Page概念,比如OS VM1个Page是4K, 4K中只要还有一个元素即使只有1个字节被访问,这个页也不会被SWAP, 换入也同样道理,读到一个字节可能会换入4K无用的内存。而Redis自己实现则可以达到控制换入的粒度。另外访问操作系统SWAP内存区域时block 进程,也是导致Redis要自己实现VM原因之一。
5. 用get/set方式使用Redis
作为一个key value存在,很多开发者自然的使用set/get方式来使用Redis,实际上这并不是最优化的使用方法。尤其在未启用VM情况下,Redis全部数据需要放入内存,节约内存尤其重要。
假如一个key-value单元需要最小占用512字节,即使只存一个字节也占了512字节。这时候就有一个设计模式,可以把key复用,几个key-value放入一个key中,value再作为一个set存入,这样同样512字节就会存放10-100倍的容量。
这就是为了节约内存,建议使用hashset而不是set/get的方式来使用Redis,详细方法见参考文献(7)。
6. 使用aof代替snapshot
Redis有两种存储方式,默认是snapshot方式,实现方法是定时将内存的快照(snapshot)持久化到硬盘,这种方法缺点是持久化之后 如果出现crash则会丢失一段数据。因此在完美主义者的推动下作者增加了aof方式。aof即append only mode,在写入内存数据的同时将操作命令保存到日志文件,在一个并发更改上万的系统中,命令日志是一个非常庞大的数据,管理维护成本非常高,恢复重建时 间会非常长,这样导致失去aof高可用性本意。另外更重要的是Redis是一个内存数据结构模型,所有的优势都是建立在对内存复杂数据结构高效的原子操作 上,这样就看出aof是一个非常不协调的部分。
其实aof目的主要是数据可靠性及高可用性,在Redis中有另外一种方法来达到目的:Replication。由于Redis的高性能,复制基本没有延迟。这样达到了防止单点故障及实现了高可用。
小结
要想成功使用一种产品,我们需要深入了解它的特性。Redis性能突出,如果能够熟练的驾驭,对国内很多大型应用具有很大帮助。希望更多同行加入到Redis使用及代码研究行列。
重新认识CSS的权重
Ghost 发表于 [2011-05-19 19:34]
今天 大白 问了一个关于CSS权重的问题:
关于选择器权重的问题 。class的权重是10 标签权重是 1 。比如说 p span{} 权重是2. 如果11标签自选择器的组合的权重11,会不会覆盖 一个class选择器权重10的 样式?
在跟他的讨论中,重新整理了我对CSS权重的理解。
在《 样式的作用域──页面重构中的模块化设计(一) 》中有做过总结,其中提到比较重要的两点:
- 权值的大小跟选择器的类型和数量有关
- 样式的优先级跟样式的定义顺序有关
在《 继承──页面重构中的模块化设计(三) 》的评论中 operafans 也提到了 标签选择器的权值永远都比一个类选器择器的权值低,无论有多少个 但一直以来都还是没能想通。
其实规则很简单: 比较同一级别的个数,数量多的优先级高,如果相同即比较下一级别的个数 ,至于各级别的优先级,大家应该已经很清楚了,就是:
important > 内联 > ID > 类 > 标签 | 伪类 | 属性选择 > 伪对象 > 继承 > 通配符 通配符 > 继承
这也就解释了为什么11个标签的定义会比不上1个类的定义,1个类加11个标签会比不上2个类的权重高。
文章地址:http://www.cssforest.org/blog/index.php?id=185