Archive for ‘ 十月, 2009

成功的Javascript开发者的7个习惯[2] —— 柔性减弱和不唐突的Javascript

——节选自《Javascript实战》(Practical Javascript,DOM Scripting,and Ajax Projects),作者:Frank W.Zammetti。

2.2 柔性减弱和不唐突的Javascript

不唐突的Javascript是一个最近才流行起来的术语。简单地说,它是一种趋势,网页中的Javascript以一种不影响页面的方式来写

不唐突的Javascript的基本原则非常简单,可以被归纳为以下几点:

保持Javascript独立。

通常允许柔性减弱。

从不使用浏览器嗅探脚本来判断一个浏览器的能力。

任何情况下,都不要写浏览器不兼容的代码,具体说,就是别写浏览器相关的Javascript代码。

合适的作用域变量。

★ 对于可访问性,避免需要鼠标事件触发的触发器。

但是,不唐突的Javascript术语对于不同的人也可以有不同的意思。一些人喜欢扩展规则并使其更加严格。另一些人喜欢修建规则并使其更灵活。关键是使用我们从以前的错误中学到的方法来实现 Javascript。

现在让我们来看看每一个基础规则的详细内容。

2.2.1 让Javascript保持独立

这个观点是把Javascript当作应用程序的一层来处理,并且使用定义明确的交互点,试着使它尽可能地独立。例如,总是从外部文件导入Javascript,并没有任何的Javascript嵌在HTML中。

我认为,这是一条比较灵活的规则。但是基本的观点是说:最大限度地保持脚本独立。

考虑一下CSS。你已经习惯于外部样式表了,对吗?那么用同样的方法来看待Javascript。这样做逻辑上把页面分成了几个部分,我们就可以很容易地找到自己感兴趣、想要修改的地方。同时它还给你留下一条重用的途径。外部保存的脚本有更好的机会在其他页面、其他站点以及其他项目中重用。虽然不能保证肯定能被使用,但它往往是有帮助的。

一些人甚至提倡通过脚本来添加事件处理函数。通常,这么做的原因是把脚本和标记完全分离,避免在修改函数名之后要修改代码中的很多地方。我不完全同意这个建议,主要是因为,一个事件处理函数是对于一个指定元素特定的,所以为什么不把它附近在那个元素上呢?对于我来说,如果我需要改变一个事件处理函数,直接找到那个元素要比找出哪个外部.js文件包含那段代码更加容易。不过有一个例外,如果处理函数是共享的(被多于一个的元素使用),这种情况下,我就会将它外部化。

到底什么样才是最好的,留给你自己去归纳。然而,我非常鼓励你保持事件处理函数尽可能的小,无论把它们放在哪。它们应该只是调用一些大块的代码或者执行一两行语句。如果你想方法让事件处理函数与元素在同一行内,那会是个更好的主意。

2.2.2 允许柔性减弱

离开了Javascript,页面也还应该工作,即使是在以衰减的形式。一个很好的例子是表单验证。不要只适用调用一个表单的函数的按钮,因为如果离开了Javascript,这个表单就不能提交了。比如,尝试下面代码清单2-1的代码,并观察一下禁用了Javascript会发生什么。


<html>

  <head>

    <script>

        function doSubmit(inForm){

            if(inForm.firstName.value == ""){

             alert("You must enter a first name");

             return false;

           } 

            if(inForm.lastName.value == ""){

             alert("You must enter a last name");

             return false;

           } 

           inForm.submit();

           return true;

        }

    </script>

  </head>

  <body>

    <form name="test" action="#" method="post">

        First name:<input type="test" name="firstName" />

        <br />

        Last name:<input type="test" name="lastName" />

        <br />

        <input type="button" onClick="doSubmit(this.form);" value="Submit" />

    </form>

  </body>

</html>

如果禁用Javascript后运行上面的代码,你将看到什么都没有发生,因为表单的提交依赖Javascript的执行,这显然是不好的。

取代它的办法是,在onSubmit时间的响应中进行验证。使用这种方法,如果Javascript启用,用户可以从客户端验证中受益。但是如果Javascript被禁用了,表单仍然可以被提交。代码清单2-2展示了它是如何工作的。


<html>

  <head>

    <script>

        function doSubmit(inForm){

            if(inForm.firstName.value == ""){

             alert("You must enter a first name");

             return false;

           } 

            if(inForm.lastName.value == ""){

             alert("You must enter a last name");

             return false;

           } 

           inForm.submit();

           return true;

        }

    </script>

  </head>

  <body>

    <form name="test" action="#" method="post" onSubmit="return doSubmit(this)">

        First name:<input type="test" name="firstName" />

        <br />

        Last name:<input type="test" name="lastName" />

        <br />

        <input type="submit" value="Submit" />

    </form>

  </body>

</html>

顺便说一下,一个致命的错误是:使用单纯的客户端验证,并假设从客户端来的任何数据都是好的。事实上,你的系统通常应该被设计成为认为从客户端来的数据都是坏的。在客户端做验证是完全可行的。不过,几乎没人愿意使用的系统把客户端验证作为唯一验证方法。

好,我们来谈一些观点。有人认为,我们应该在所有Web应用上附加一些不唐突的原则和一些合理的、柔性衰减的安全约束。我并不同意这种观点,甚至可以说,我认为这种观点完全是无原则的。

[...]

我们所处的时代是“RIA(Rich Internet Application,富因特网应用)”时代,RIA开始统治因特网。比如说,Google,现在就处在把一整套office软件套件放在网上给所有用户使用的早期时代(见http://docs.google.com)。你认为所有开发人员都会力图遵守所有不唐突的原则吗(除了少数最低限度的之外)?并且这么做了之后还能用?几乎可以肯定地说这不可能,因为对于这种高端应用来说,这就是不肯能的任务。让我说得更明白些:在RIA世界里,大多数这里描述的不唐突的要求仍然是可为的。只是其中的某些可能不能做到罢了。

这就是网站和Web应用之间的差距。从某种意义上来说,网站的目的是散播信息。它只有很有限度的用户交互需求,通常来说,简单的HTML表单就足够好用了。在一个网站里,所有这里描述的规则几乎都应该遵守,而且更重要的是,这些规则是可以遵守的。相对来说,Web应用则更复杂并且需要更高级的用户交互。它们就是为了替换胖客户端、应用程序等那些用户已经习惯了几十年的东西。这些用户需要功能强大同时又简洁的动态交互界面、铃声和报警声,以及一些不写代码就不能实现的特性——并且有些代码必须在客户端里组织起来。在这种场合,我的观点是:遵守这些规则就是不合理的,会导致无数项目的失败。

不过,对于任何在Web上给公众使用的东西,你都毫无疑问地应该争取优秀的可用性、合理的柔性衰减,以及所有其他不唐突的Javascript目标。对于无法实现这些目标的地方,我们应该有很清晰、和合理的原因,并且绝对可以确信:如果要实现这些目标,你的应用就无法实现。(我汗-_-|||还好语文学得好,呃呃)

所以,简而言之,我认为你应该审视一下你正在做什么,以及你的目标是什么,并决定这些指导哪些应该遵循。不要犯错误,我相信你会试着遵守全部这些规则。但是我估计那有时并不可能。再说一次,这是我个人的意见,请根据自己最好的判断形成自己的意见。

2.2.3 不要使用浏览器嗅探例程

与其使用浏览器嗅探脚本去确定一个浏览器的能力,还不如检查对象的存在和对象的能力。这个问题的补充是,只是由于开发者的懒惰而引起的Javascript错误,比如在访问一个给定对象之前没有检查它是否存在,是无理且不好的。

一个例子,看看下面的代码:


function setContent(inobj,inContent{

    inObject.innerHTML = inContent;

}

);

这里,如果对象inObj并不支持innerHTML,就会出现一个错误。可能由于innerHTML不是DOM中的一个标准的部分(虽然,实际上我不知道有哪个浏览器没实现它)。重写这部分来避免这个错误很简单:

function setContent(inobj,inContent{

   if(inObj.innerHTML){

      inObject.innerHTML = inContent;

    }

    }

);

[/javascript]

通常像这样检查是个好习惯,它实际上是确定一个浏览器是否支持一个特定的功能。这样做的一个最好的例子是基本的Ajax编程,你需要一个XMLHttpRequest对象的实例。不幸的是,不同的浏览器使用不同的方法来支持这个对象的使用。然而,你可以检查不同的对象,并基于它们的存在或不存在,来分支代码,像这样:


var xhr = null;

if(window.XMLHttpRequest){

    xhr = new XMLHttpRequest();

}

else if(window.ActiveXObject){

    xhr = new ActiveXObject(Microsoft.XMLHTTP);

}

然而,如果能写根本不需要分支的代码会更好,但是那通常不太可能。浏览器嗅探是个坏主意,因为,很多开发者多年来的体会是,你总是需要保持嗅探代码的更新,以便让它能识别新的浏览器。对象存在性的检查就没那么脆弱了,通常不需要重写代码来处理新的浏览器,所以这个技术比嗅探浏览器好得多。

做设计最痛苦滴事是…

design_is____by_vevrca

在站酷看到不少同行发帖子抱怨,讨论做设计最痛苦的事。当然,最痛苦的事莫过于稿子一改再改,最后完全违背设计审美和设计的初衷。我的经验是,整个稿子中你觉得最得意的地方往往会被BOSS或被自己“咔嚓”掉,不知道是不是只有我遇到过这种情况。

转眼接受辐射两周年了,在这两年的设计生涯中(其实我不认为自己是设计师,因为我还不够水平),尽管我最痛苦的事就是跟BOSS沟通关于版面修改的事,而事实上,无论是客户的稿子还是BOSS的稿子,算起来,我修改的次数是算少的。

我觉得理性点看这里面其实是个预期值的问题。盲目地按照自己觉得美的方式去设计页面没有任何好处,因为我不是艺术家,顶多只是比对方稍具专业眼光而已。

一个网站设计出来是否会因为BOSS不满意而成为飞机稿很大程度决定于对方的期望值有多高,你有多了解他真实的需求。或许漂亮对他来说只是次要的呢?或许他只是需要更多可以吸引客户的广告位,无论它们有多么难看或这个决定有多么影响用户体验(他就是要!!!);或许他只是想做一个比竞争对手稍微漂亮点的网站而已。

设计页面之前我会千方百计了解他们的需求(多数时候这个需求只有两句话),了解他们喜欢的风格,喜欢的配色(这个比较好办,直接问),了解他们的业务模式和商业目的(哪怕非常模糊)。了解他期望这个东西出来以后给他一种什么他想要的结果。当了解了这些东西以后,基本上,一个稿子做出来后命运如何,我自己已经猜到八成。比较痛苦的情形是对方根本不知道自己要什么,直到你的稿子出现以后,他突然非常清晰地知道了自己不要什么。

在这点上,我从来没有任何性格也不坚持自己的原则。一个东西你自己觉得再好对方却不喜欢用的话,那也不过是在浪费双方的时间和表情而已。世界上没有完美的老板也没有完美的设计师。在这点上,我倾向于让自己去做一个平衡者。在纯粹审美和客户需求之间,在服务提供商和用户之间,尽力找出一个较好的解决办法。

记得接受第一份网页设计师的工作时,老板是个想法充满主观色彩的人,事无巨细并且非常固执。由于稿子改得太频繁,我经常觉得窝火,觉得姐们这种人才不该受这种气。但是后来有一天我忽然明白了,真正优秀的作品其实第一眼就能得到多数人的认可,那些需要再三琢磨的作品,是因为它本身就存在软肋。别人的意见不是没有任何道理的,更多时候是你不愿意仔细去想不愿意接受重做这个后果而已。

我还觉得,其实对待BOSS的意见设计师本身不该带有过多的偏见,因为双方的立场是不同的。如果你非常不爽他的话,你就辞职好了。当你为你精致的设计感到满意时,或许他在为那些看起来太小的广告位而发愁。假设这就是他的需求,大量的广告位,那么我告诉自己我所能做到的就是:给他大量的广告位,并且尽量以不那么让人讨厌和符合整体风格的方式实现。如果做出来的结果奇丑无比并且所有人都知道这就是你做的,那就扭过头去不看好了。

无论是否愿意承认,在漫长的痛苦的修改和沟通中,其实是在进步的。在设计的路上,我一直是以某种类似雇佣兵的心态在做事,但是从来不敢荒废自己的技术。

事实上我很怕做设计,因为我什么也不懂,却偏偏的眼睛长在头顶上了。每当对比自己和别人的作品的时候,我通常很想自杀。哈哈。所以做设计对我来说最痛苦的事不是稿子变成飞机,而是稿子想不出来,搞不定。没有灵感硬想的时候不但痛苦且让我恐惧。但是我知道只有坚持下去,这样才能进步,哪怕是缓慢的,哪怕是没有结果的。

jQuery性能优化指南(3)

8,尽量使用ID代替Class

前面性能优化已经说过,ID选择器的速度是最快的。所以在HTML代码中,能使用ID的尽量使用ID来代替class。
看下面的一个例子:

// 创建一个list;

var $myList = $("#myList");

var myListItems = "<ul>";

for (i = 0; i < 1000; i++) {
     myListItems += '<li class="listItem' + i + '">This is a list item</li>'; //这里使用的是class
 }

myListItems += "</ul>";

$myList.html(myListItems);

// 选择每一个 li

 for (i = 0; i < 1000; i++) {
    var selectedItem = $(".listItem" + i);
}

在代码最后,选择每个li的过程中,总共用了5066毫秒,超过5秒了。

接着我们做一个对比,用ID代替class:

// 创建一个list

var $myList = $("#myList");

var myListItems = "<ul>";

for (i = 0; i < 1000; i++) {
    myListItems += '<li id="listItem' + i + '">This is a list item</li>'; //这里使用的是id
}

myListItems += "</ul>";

$myList.html(myListItems);

 // 选择每一个 li

for (i = 0; i < 1000; i++) {
     var selectedItem = $("#listItem" + i);
}

在上段代码中,选择每个li总共只用了61毫秒,相比class的方式,将近快了100倍。

9,给选择器一个上下文

jQuery选择器中有一个这样的选择器,它能指定上下文。
jQuery( expression, context );

通过它,能缩小选择器在DOM中搜索的范围,达到节省时间,提高效率。
普通方式:

$(".myDiv")

改进方式:

$(".myDiv" , $("#listItem") )

10,慎用 .live()方法(应该说尽量不要使用)

这是jQuery1.3.1版本之后增加的方法,这个方法的功能就是为新增的DOM元素动态绑定事件。
但对于效率来说,这个方法比较占用资源。所以请尽量不要使用它。

例如有这么一段代码:

<script type="text/javascript">

$(function(){
 $("p").click(function(){
     alert( $(this).text() );
 });
$("button").click(function(){
    $("<p>this is second p</p>").appendTo(”body”);
});
})

</script>
<body>

<p>this is first p</p> <button>add</button>

</body>

运行后,你会发现新增的p元素,并没有被绑定click事件。

你可以改成.live(”click”)方式解决此问题,代码如下:

$(function(){

$("p").live("click",function(){ //改成live方式
     alert( $(this).text() );
 });
$("button").click(function(){ $("<p>this is second p</p>").appendTo("body"); });})

但我并不建议大家这么做,我想用另一种方式去解决这个问题,代码如下:

$(function(){

$("p").click(function(){

    alert( $(this).text() );

});
$("button").click(function(){

    $("<p>this is second p</p>").click(function(){  //为新增的元素重新绑定一次

            alert( $(this).text() );

    }).appendTo("body");
});
})

虽然我把绑定事件重新写了一次,代码多了点,但这种方式的效率明显高于live()方式,特别是在频繁的DOM操作中,这点非常明显。

11,子选择器和后代选择器

后代选择器经常用到,比如:

$("#list p");

后代选择器获取的是元素内部所有元素。

而有时候实际只要获取子元素,那么就不应该使用后代选择器。应该使用子选择器,代码如下:

$("#list > p");

12,使用data()方法存储临时变量

下面是一段非常简单的代码,


$(function(){

    var flag = false;

    $("button").click(function(){

        if(flag){

            $("p").text("true");

            flag=false;

        }else{

            $("p").text("false");

            flag=true;

        }

    });

})

改用data()方式后,代码如下:

$(function(){

    $("button").click(function(){

        if( $("p").data("flag") ){

            $("p").text("true");

            $("p").data("flag",false);

        }else{

             $("p").text("false");

             $("p").data("flag",true);

        }

    });

})

成功的Javascript开发者的7个习惯[1] —— 更多面向对象的Javascript

——节选自《Javascript实战》(Practical Javascript,DOM Scripting,and Ajax Projects),作者:Frank W.Zammetti。

2.1 更多面向对象的Javascript

当很多Javascript程序员开始使用Javascript的时候,他们通常并没有意识到这个语言提供了一些面向对象的概念。当然,Javascript完全不要求使用对象!(其他它隐含地会使用对象,因为Javascript在很多场合会使用内置对象,但是你的代码自身不必是面向对象的)

条条大路通罗马,同样,在Javascript中,也有不止一种的方法来创建对象。

2.1.1 简单的对象创建

可能最简单的创建对象的方法是用一个新的Object开始,然后向其中添加内容。想要创建一个新的Object,你只要这么做:


var newObject = new Object();

变量newObject现在指向一个Object的实例,Object是Javascript中所有对象的基类。要给它添加一个元素,比如说,增加一个叫firstName的元素,你要做的只是:


newObject.firstName = "Frank";

从代码中的这个位置开始,newObject.firstName就将含有一个值”Frank”,除非它在后面被修改了。你也可以很容易地添加函数:


newObject.sayName = function(){

alert(this.firstName);

}

现在newObject.sayName()调用的结果,是弹出一个”Frank”的警告信息。与大多数成熟的面向对象语言不同的是,在Javascript中,你不必为一个对象实例创建类或蓝图。你可以像这里所写的那样,在运行时创建它。在对象的整个生命周期中都可以这么做。在网页中,这就意味着你可以在任何时候给对象添加属性和方法。

事实上,Javascript实现只是把所有对象当作关联数组。然后给数组加上了一个面具,使它的语法看起来更像JAVA或C++,使用点分隔法表示。为了强调这一点,你可以像这样检索newObject中firstName字段的值:


var theFirstName = newObject["firstName"];

同样,可以这样调用sayName()函数:


newObject["sayName"]();

这个简单的东西可以算是很多强大功能的基础。比如,假如你想基于某种逻辑调用某个对象的方法又如何呢?噢,你可以这么做:


var whatFunction;

 if(whatVolume == 1){

  whatFunction = "sayName";

}

if(whatVolume == 2){

  whatFunction = "sayLoudly";

}

假设我们已经将函数sayLoudly()添加到newObject,这个函数在firstName字段中的alert()之前调用toUpperCase(),然后我们可以基于一个变量的值,来控制对象“大声”(全部大写)地或者“温柔”(如上所示,全部小写)地说出名字。

当向一个对象添加函数的时候,你可以使用已存在的函数。作为例子,让我们来继续添加那个sayLoudly()函数:


function sayLoudly(){

  alert(this.firstName.toUpperCase());

}

newObject.sayLoudly = sayLoudly;

请注意这里的this关键字的使用方法。可以说,它指向的对象将会在运行时动态计算。因此,在这个例子中,this指向的是函数sayLoudly()作为其成员的那个类——这里是newObject。有意思的是,如果sayLoudly()完全是另一个对象的一部分,关键字this就会引用另一个对象。这种运行时绑定也是Javascript面向对象实现的一个非常强大的特性,因为它允许代码的共享,本质上来说,是一种继承的形式。

2.1.2 使用JSON创建对象(参考《JSON入门指南》

由于JSON(Javascript Object Notation,Javascript对象表示法)在Ajax请求中的使用而被越来越广泛的关注,所以很多人了解了它。然而,一些人还并不知道JSON实际上是Javascript规范中的一个核心部分,而且它在Ajax登台之前就已经存在了。它的最初目的是为了快速简便地定义复杂的对象关系图,也就是那些嵌套于其他对象中的对象的实例。虽然它看上去是如此的简单,但它允许了创建对象的另外一种方式。

还记得我们曾说过,Javascript里的对象只是隐藏在面具下的关联数组吗?这就是JSON可运转的因素。让我们来看看如何使用JSON来创建前面例子中的newObject:


function sayLoudly(){ 

  alert(this.firstName.toUpperCase());

}

 

var newObject ={

firstName:"Frank",

sayName:function(){alert(this.firstName);},

sayLoudly:sayLoudly

};

使用JSON和定义一个数组非常相似,除了你需要使用花括号而不是方括号。注意函数可以是内联的,也可以引用外部函数。(看到sayLoudly可能有一些困惑,但是Javascript理解为第一个sayLoudly是对象的一个成员,而第二个sayLoudly
是对一个已存在的对象的引用。)

在JSON中,你可以随意地嵌套对象定义来创建对象的层级关系。例如,我们向newObject中添加一个名为LastName的对象:

function sayLoudly(){ 

  alert(this.firstName.toUpperCase());

}

 

var newObject ={

firstName:"Frank",

sayName:function(){alert(this.firstName);},

sayLoudly:sayLoudly,

LastName:{

  lastName:"Zammetti",

  sayName: function(){alert(this.lastName);}

  }

};

然后,你可以通过下面的调用来显示姓的部分:


newObject.LastName.sayName();

2.1.3 类的定义
在Javascript中,其实所有的东西都是一个对象。这是事实,只有一小部分例外,比如一些内置的原语。这部分讨论的最重要的一点是,函数本身就是对象。你已经了解到如何创建一个Object的实例,并向其中添加属性和方法了,但是那意味着每次创建对象的一个新实例时,你实际上都需要从零开始创建。这里肯定有更好的方法,不是吗?当然有:创建一个类。

在Javascript中,类实际上就是一个函数。这个函数同样被当作类的构造函数来提供服务。那么例如,让我们把newObject写作一个类,重命名为newClass:


function newClass(){

  alert("constructor");

  this.firstName = "Frank";

  this.sayName = function(){

    alert(this.firstName);

}

var nc = new  newClass();

nc.sayName();

}

执行这段代码时,你会先后看到两个警告信息:首先,当执行到var nc = new  newClass();这行的时候,弹出“constructor”,然后,当执行到nc.sayName();这行的时候弹出“Frank”。你想要创建多少newClass的实例就可以创建多少,而且它们将会含有同样的属性和方法。一旦创建,他们还将弹出同样的警告信息,firstName含有同样的初始值。简而言之,你为创建newClass对象创建了一个蓝图,你定义了一个类。

但是,由此引出的一个问题是:newClass的每一个实例都含有firstName的一个副本和sayName方法的一个副本,那么每个实例都占用两个更多的内存。newClass的每个副本都有各自的firstName副本,这个可能是你想要的,但是如果所有的实例都可以共享相同的sayName()副本的话,是不是更好了,能否节省些内存?很明显,在这个例子中,我们并不能有大量的内存节省,但是你可以设想一些更大的代码的情况,那些场合中,很可能差别就更大了。幸运的是,有一种方法可以这样做。

2.1.4 原型

Javascript中的每一个独立的对象都有一个与之关联的原型(prototype)属性。在我所知道的其他语言中,并没有与prototype完全相等的东西,但是它可以被看作一个简化的继承形式。基本上,它工作的方式是:当你构造一个对象的新实例时,定义在对象原型中的所有属性和方法,在运行时都会附着在那个新的实例上。

我知道,第一次看到这个概念时,可能有一些难以理解,但幸运的是,它很容易演示:


function newClass(){ 

  this.firstName = "Frank";

}

newClass.prototype.sayName = function(){

  alert(this.firstName);

}

var nc = new newClass();

nc.sayName();

执行的时候,这个代码会弹出同样的警告信息说“Frank”。与前面的例子不同的是,无论你创建了多少个newClass的实例,在内存中sayName()函数只会有一个单独的实例。这个方法实际上是附加在每个实例上,而且this关键字还是在运行时被计算的。所以this通常指向它所属的那个特定的newClass实例。例如,如果你有两个newClass的实例分别叫做nc1和nc2,然后一个对nc1.sayName()的调用将this指向nc1,一个对nc2.sayName()的调用将this指向nc2。

2.1.5 你应该使用哪种方法呢

前面所说的每个方法都有各自的优点和缺点,而且我怀疑是否存在孰好孰坏的共识。它们在功能都是相同的,所以很大程度上它取决于你更喜欢代码看起来像什么样子。也就是说,我想有一些常用的准则来帮助你。

最重要的一个可能是,如果你要创建一个类,这个类非常大,而且它可能会有复杂的实例,那么几乎可以肯定要使用原型的方法。这样可以带来最好的内存使用效率,这通常是一个重要的目标。

如果你要创建一个单独的类而且知道这个类将只有一个实例,我个人会倾向定义一个类。对我来说,这样的代码是逻辑化最强、最类似于更全面的面向对象语言的,因此可能更易于项目中的新开发人员理解。

如果(a)你的对象层级关系嵌套层次很多和/或(b)你需要在一个动态方式中定义一个对象(一段逻辑代码的输出结果),那么,JSON方法可能是一个好的选择。如果需要将对象序列化并且通过网络进行传输,JSON也几乎非常明显是首选。如果你需要重构一个从服务器传来的对象时也是如此。我怀疑做这些事情的时候,没有比JSON更简单的方法,这不是小范围的怀疑,而是因为这些事情就是设计JSON 的目的。

2.1.6 面向对象的好处

无论你选择哪种方法,将代码面向对象化都有很多好处。一个重要的好处就是,每一个对象本质上就是一个命名空间。可以用此来模拟Java和C#的包,就像在下一章中会看到的。

另一个好处是可以使用对象来隐藏数据。看看下面的代码:

 

function newClass(){

  this.firstName = "Frank";

  lastName = "Zammetti";

}

var nc = new newClass();

alert(nc.firstName);

alert(nc.lastName);

执行这段代码会有两个警告信息:第一说“Frank”,第二个说“undefined”。这是因为lastName字段在lastName的实例外是不可访问的。请注意字段定义的不同。任何使用this关键字定义的字段,比如firstName那样,都可以在类之外访问。而任何没有this关键字定义的字段,都只能在类的内部访问。这个规则对于方法也同样适用

同样,不要忘记Javascript的内置对象可以通过使用它们的原型来扩展,事实上,Javascript的名为Prototype的库就是在做这个事情,这些你将会在2.6节中看到。但是,如果不小心的话,你真的可能把事情搞糟,所以扩展内置对象时要谨慎。

你可以从其他的对象中“借”函数,并把它们添加到自己的对象中。例如,假设你想要通过输出newClass本身来显示newClass的firstName字段。为实现这个目标,你实现了一个toString()函数。再假设你还想在它上面使用String对象中的toUpperCase()函数。很简单,我们可以这样做:

 


function newClass(){

  this.firstName = "Frank";

  this.toUC = String.toUpperCase;

  this.toString = function(){

  return this.toUC(this.firstName);

  }

}

var nc = new newClass();

alert(nc);

 执行这段代码,结果是一个警告提示说“Frank”.注意调用了toString()函数,但并不是作为firstName String对象的一个方法。取而代之的,是通过指向它的一个引用调用的,这个引用是newClass的属性之一,名为toUC。这是一个很好的功能,尤其是当你创建自己的对象之后,又想创建一个新的,并使用原来的代码。那你不用复制、剪切及粘贴,只需引用其他类里的已存在的方法就可以了。

wordpress代码高亮插件:SyntaxHighlighter Evolved下载地址和使用方法

一直对wordpress自带的代码高亮插件心怀不满,外观不好看也就罢了,编辑的时候出错率忒高,想将就都不行了。昨晚在网上搜罗,找到一款普遍口碑较好的wp插件:SyntaxHighlighter Evolved(作者:Andrew Ozz of Automattic)。

本来很简单的一个事情,却折腾了我整一个小时,原因就是偷懒方法错了。原来互联网上名曰SyntaxHighlighter的插件还真不少。其中有纯javascript插件(用来制作demo不错),也有专为wordpress制作的插件;就这样,我在网上找到了几个教程七拼八凑地实施,先是上传了错误的插件导致安装时报错,后来又用错了调用的方法。惰性啊惰性,不肯耐心花点时间比较和阅读文档而是匆忙地实施,结果花了更多的时间!!!

下面是有关SyntaxHighlighter Evolved的下载链接和安装方法:

下载地址:http://wordpress.org/extend/plugins/syntaxhighlighter/

使用方法:

1.上传插件到 wp-contents/plugins 文件夹并在博客后台启用————确实是废话。

2.在写文章时,在html模式下 使用这样的代码:

使用[language]的形式将需要高亮显示的代码包住,例如:

[sourcecode]code here[/sourcecode]

支持代码的类型可见:http://alexgorbatchev.com/wiki/SyntaxHighlighter:Brushes

3.效果预览

screenshot-1

附:

另外一款口碑很好的代码高亮插件,Google Syntax Highlighter for WordPress

另外一些互联网上比较推荐的代码高亮插件:http://paranimage.com/7-wordpress-syntax-highlight-plugin/

jQuery性能优化指南(2)

4,对直接的DOM操作进行限制

这里的基本思想是在内存中建立你确实想要的东西,然后更新DOM 。
这并不是一个jQuery最佳实践,但必须进行有效的JavaScript操作,直接的DOM操作速度很慢。

例如,你想动态的创建一组列表元素,千万不要这样做,如下所示:


var top_100_list = [...], // 假设这里是100个独一无二的字符串

$mylist = $("#mylist"); // jQuery 选择到 <ul> 元素

for (var i=0, l=top_100_list.length; i<l; i++){
  $mylist.append("<li>" + top_100_list[i] + "</li>");
}

我们应该将整套元素字符串在插入进dom中之前先全部创建好,如下所示:

var top_100_list = [...],$mylist = $("#mylist"), top_100_li = "";
// 这个变量将用来存储我们的列表元素

for (var i=0, l=top_100_list.length; i<l; i++){
   top_100_li += "<li>" + top_100_list[i] + "</li>";
}

$mylist.html(top_100_li);

注:记得以前还看过一朋友写过这样的代码:


for (i = 0; i < 1000; i++) {

    var $myList = $("#myList");

    $myList.append("This is list item" + i);

}

呵呵,你应该已经看出问题所在了。竟然把#mylist循环获取了1000次!!!

5,冒泡

除非在特殊情况下, 否则每一个js事件(例如:click, mouseover等.)都会冒泡到父级节点。
当我们需要给多个元素调用同个函数时这点会很有用。

代替这种效率很差的多元素事件监听的方法就是, 你只需向它们的父节点绑定一次。

比如, 我们要为一个拥有很多输入框的表单绑定这样的行为: 当输入框被选中时为它添加一个class。传统的做法是,直接选中input,然后绑定focus等,如下所示:


$("#entryform input").bind("focus", function(){
    $(this).addClass("selected");
}).bind("blur", function(){
    $(this).removeClass("selected");
});

当然上面代码能帮我们完成相应的任务,但如果你要寻求更高效的方法,请使用如下代码:


$("#entryform").bind("focus", function(e){
    var $cell = $(e.target); // e.target 捕捉到触发的目标元素
    $cell.addClass("selected");
}).bind("blur", function(e){
    var $cell = $(e.target);
    $cell.removeClass("selected");
});

通过在父级监听获取焦点和失去焦点的事件,对目标元素进行操作。
在上面代码中,父级元素扮演了一个调度员的角色, 它可以基于目标元素绑定事件。
如果你发现你给很多元素绑定了同一个事件监听, 那么现在的你肯定知道哪里做错了。

伟大啊伟大,抄书的徐小花到此一游!!!

同理,在Table操作时,我们也可以使用这种方式加以改进代码:
普通的方式:


$("#myTable td").click(function(){
    $(this).css("background", "red");
});

改进方式:


$("#myTable").click(function(e) {
     var $clicked = $(e.target);
     $clicked.css("background", "red");
});

假设有100个td,在使用普通的方式的时候,你绑定了100个事件。
在改进方式中,你只为一个元素绑定了1个事件。
至于是100个事件的效率高,还是1个事件的效率高,相信你也能自行分辨了。

6,推迟到 $(window).load

jQuery对于开发者来说有一个很诱人的东西, 可以把任何东西挂到$(document).ready下。
尽管$(document).rady 确实很有用, 它可以在页面渲染时,其它元素还没下载完成就执行。
如果你发现你的页面一直是载入中的状态,很有可能就是$(document).ready函数引起的。

你可以通过将jQuery函数绑定到$(window).load 事件的方法来减少页面载入时的CPU使用率。
它会在所有的html(包括iframe)被下载完成后执行。


$(window).load(function(){
    // 页面完全载入后才初始化的jQuery函数.
});

一些特效的功能,例如拖放, 视觉特效和动画, 预载入隐藏图像等等,都是适合这种技术的场合。

7,压缩JavaScript

压缩和最小化你的JavaScript文件。

在线压缩地址: http://dean.edwards.name/packer/
压缩之前,请保证你的代码的规范性,否则可能失败,导致Js错误。

英文原文:http://www.artzstudio.com/2009/04/jquery-performance-rules/
中文翻译:http://rlog.cn/350 & http://cssrain.cn

jQuery性能优化指南(1)

强烈推荐这一系列的文章,它们让我从根本上理解和开始思考一些以前自己未曾注意到的问题。或许对牛人来说这些问题微不足道,我却受益匪浅啊哇哈哈哈。

1、总是从ID选择器开始继承
 在jQuery中最快的选择器是ID选择器,因为它直接来自于JavaScript的getElementById()方法。
例如有一段HTML代码:

<div id="content">
<form action="#" enctype="application/x-www-form-urlencoded" method="post">
<h2>交通信号灯</h2>
<ul id="traffic_light">
 <li>
  <input class="on" name="light" type="text" value="red" /> 红色
 </li>
 <li>
  <input class="off" name="light" type="text" value="yellow" /> 黄色
 </li>
 <li>
  <input class="off" name="light" type="text" value="green" /> 绿色
 </li>
</ul>
 <input id="traffic_button" class="button" type="text" value="Go" />
</form>
</div>

如果采用下面的选择器,那么效率是低效的。


var traffic_button = $("#content .button");

因为button已经有ID了,我们可以直接使用ID选择器。如下所示:


var traffic_button = $("#traffic_button");

当然,这只是对于单一的元素来讲。如果你需要选择多个元素,这必然会涉及到 DOM遍历和循环,为了提高性能,建议从最近的ID开始继承。

如下所示:

 


var traffic_lights = $("#traffic_light input");

2,在class前使用tag(标签名)

在jQuery中第二快的选择器是tag(标签)选择器( 比如:$(”head”) )。
跟ID选择器类似,因为它来自源生的getElementsByTagName() 方法。

继续看刚才那段HTML代码:

<div id="content">
<form action="#" enctype="application/x-www-form-urlencoded" method="post">
<h2>交通信号灯</h2>
<ul id="traffic_light">
 <li>
  <input class="on" name="light" type="text" value="red" /> 红色
 </li>
 <li>
  <input class="off" name="light" type="text" value="yellow" /> 黄色
 </li>
 <li>
  <input class="off" name="light" type="text" value="green" /> 绿色
 </li>
</ul>
 <input id="traffic_button" class="button" type="text" value="Go" />
</form>
</div>

比如需要选择 红绿 单选框,
那么可以使用一个tag name来限制(修饰)class ,如下所示:

var active_light = $("input.on");

当然也可以结合 就近的ID,如下所示:

var active_light = $("#traffic_light input.on")

在使用tag来修饰class的时候,我们需要注意以下几点:

(1) 不要使用tag来修饰ID,如下所示:

var content = $("div#content");

这样一来,选择器会先遍历所有的div元素,然后匹配#content。
(好像jQuery从1.3.1开始改变了选择器核心后,不存在这个问题了。暂时无法考证。)

(2)不要画蛇添足的使用ID来修饰ID,如下所示:

var traffic_light = $("#content #traffic_light");

注:如果使用属性选择器,也请尽量使用tag来修饰,如下所示:

$('p[row="c3221"]').html();

而不是这样:

$('[row="c3221"]').html();

3,将jQuery对象缓存起来

把jQuery对象缓存起来,就是要告诉我们:要养成将jQuery对象缓存进变量的习惯

下面是一个jQuery新手写的一段代码:

$("#traffic_light input.on").bind("click", function(){ … });
$("#traffic_light input.on").css("border", "1px dashed yellow");
$("#traffic_light input.on").css("background-color", "orange");
$("#traffic_light input.on").fadeIn("slow");

但切记不要这么做。

我们应该先将对象缓存进一个变量然后再操作,如下所示:

var $active_light = $("#traffic_light input.on");
$active_light.bind("click", function(){ … });
$active_light.css("border","1px dashed yellow");
$active_light.css("background-color", "orange");
$active_light.fadeIn("slow");

记住,永远不要让相同的选择器在你的代码里出现多次.

注:(1)为了区分普通的JavaScript对象和jQuery对象,可以在变量首字母前加上 $ 符号。
(2)上面代码可以使用jQuery的链式操作加以改善。如下所示:

var $active_light = $("#traffic_light input.on");
$active_light.bind("click", function(){ … })
.css("border", "1px dashed yellow")
.css("background-color", "orange")
.fadeIn("slow");

如果你打算在其他函数中使用jQuery对象,那么你必须把它们缓存到全局环境中。
如下代码所示:

// 在全局范围定义一个对象 (例如: window对象)

window.$my = {

head : $("head"),

traffic_light : $("#traffic_light"),

traffic_button : $("#traffic_button")

};

function do_something(){

// 现在你可以引用存储的结果并操作它们

var script = document.createElement("script");

 $my.head.append(script);

// 当你在函数内部操作是, 可以继续将查询存入全局对象中去.

$my.cool_results = $("#some_ul li");

$my.other_results = $("#some_table td");

 // 将全局函数作为一个普通的jquery对象去使用.

$my.other_results.css("border-color", "red");

 $my.traffic_light.css("border-color", "green");

}

//你也可以在其他函数中使用它

转自http://www.cssrain.cn/article.asp?id=1351

Simpsons最新动态:辛普森大妈上PlayBoy 了!

激动啊激动!!!必须承认,本人患有辛普森迷狂综合症!!!

simpson_playboy

11月刊的PlayBoy 将以动画片《The Simpsons/辛普森家庭》当中的辛普森老妈Marge Simpson 作为封面人物。啊哈。

媒体戏称,这可能是荷马大叔(辛普森中的老爸)最不愿意看到的,同时又是巴特(辛普森中的儿子Bart)最骄傲的事情了。

除了这个封面大图之外,在内页PlayBoy 还做了一个对Marge Simpson 的专访多达2页的容量,让Marge Simpson 真的从荧幕中活了起来。

PlayBoy 的发言人自信的说道:我们知道20岁的小伙子就喜欢这样的。来源news.yahoo

===============================================

这不是恶搞,玛姬·辛普森 (Marge Simpson) 抛开了家庭主妇保守的形象,画面上的她仍然梳着标志性高竖着的蓝色头发,但却是全裸上阵,尺度最有突破性。

simpson_playboy2 

    
这是《花花公子》(PLAYBOY) 第一次不是用艳丽性感的兔女郎作封面。它的发言人说让玛姬·辛普森 (Marge Simpson) 当封面女郎很有创意,而且并不离谱,因为不仅可以庆祝动画片《辛普森一家》播映20周年,《花花公子》(PLAYBOY) 老板赫夫纳是《辛普森一家》的忠实粉丝,如此还能与年轻读者拉近距离。

simpson_playboy3

《花花公子》(PLAYBOY) 1971年10月刊上封面女郎Darine Stern的姿势是玛姬·辛普森 (Marge Simpson) 性感姿势的原型

simpson_playboy4

玛姬·辛普森 (Marge Simpson) 虽然之前也登过杂志封面,但基本上都是家庭主妇的形象

部分应用自煎蛋海报

IE中打开UTF-8编码title为中文的网页会显示空白页的问题[转]

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>无标题文档</title>

如果位置换过来了见下面:

<title>无标题文档</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

那么页面在IE下显示空白。

如果title是字母而非文字时,显示正确。即:

<title>hey this is a test</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

也显示正确,不会出现空白。

原因:这个问题要从浏览器解析html的方式讲起。浏览器读取了页面的html代码后开始进行解析。解析前浏览器要先知道页面的编码方式,然后根据编码方式进行解码,然后才能开始解析。IE 解析网页编码时是 HTML 內的标识优先的,然后是 HTTP header ;而mozilla 系列的浏览器刚刚好相反。一般情况在,很多人是把排在最前面,并且在title中就出现了UTF-8中文,这样, IE在解析时,就先遇到UTF-8,不往下解析了。

原文地址:http://www.cnblogs.com/yuzhongwusan/archive/2009/10/10/1580073.html

更多解释可见:http://www.cnblogs.com/xlong1900/archive/2008/02/21/1076769.html

关于“杀人后处理尸体的方法”

题目有点标题党,本人只是照抄而已。下午逛了一下豆瓣,在“文艺青年装逼会”小组发现原来有人跟我一样平时没事就思考这个问题,草草看了一把,方法似乎还不太科学哈。处理尸体和制造不在场证明这两个问题一直是我脑子无聊时的至爱,我本来是打算等老了没事儿干了慢慢琢磨制作几个具体方案的。哇哈哈哈。

 

kill

豆瓣的小组果然强大得让人无言。。。基本上人类想象力所及之处就有豆瓣“小组”的存在,呵呵。