*:first-child {
margin-top: 0 !important;
}

body>*:last-child {
margin-bottom: 0 !important;
}

/* BLOCKS
=============================================================================*/

p, blockquote, ul, ol, dl, table, pre {
margin: 15px 0;
}

/* HEADERS
=============================================================================*/

h1, h2, h3, h4, h5, h6 {
margin: 20px 0 10px;
padding: 0;
font-weight: bold;
-webkit-font-smoothing: antialiased;
}

h1 tt, h1 code, h2 tt, h2 code, h3 tt, h3 code, h4 tt, h4 code, h5 tt, h5 code, h6 tt, h6 code {
font-size: inherit;
}

h1 {
font-size: 28px;
color: #000;
}

h2 {
font-size: 24px;
border-bottom: 1px solid #ccc;
color: #000;
}

h3 {
font-size: 18px;
}

h4 {
font-size: 16px;
}

h5 {
font-size: 14px;
}

h6 {
color: #777;
font-size: 14px;
}

body>h2:first-child, body>h1:first-child, body>h1:first-child+h2, body>h3:first-child, body>h4:first-child, body>h5:first-child, body>h6:first-child {
margin-top: 0;
padding-top: 0;
}

a:first-child h1, a:first-child h2, a:first-child h3, a:first-child h4, a:first-child h5, a:first-child h6 {
margin-top: 0;
padding-top: 0;
}

h1+p, h2+p, h3+p, h4+p, h5+p, h6+p {
margin-top: 10px;
}

/* LINKS
=============================================================================*/

a {
color: #4183C4;
text-decoration: none;
}

a:hover {
text-decoration: underline;
}

/* LISTS
=============================================================================*/

ul, ol {
padding-left: 30px;
}

ul li > :first-child,
ol li > :first-child,
ul li ul:first-of-type,
ol li ol:first-of-type,
ul li ol:first-of-type,
ol li ul:first-of-type {
margin-top: 0px;
}

ul ul, ul ol, ol ol, ol ul {
margin-bottom: 0;
}

dl {
padding: 0;
}

dl dt {
font-size: 14px;
font-weight: bold;
font-style: italic;
padding: 0;
margin: 15px 0 5px;
}

dl dt:first-child {
padding: 0;
}

dl dt>:first-child {
margin-top: 0px;
}

dl dt>:last-child {
margin-bottom: 0px;
}

dl dd {
margin: 0 0 15px;
padding: 0 15px;
}

dl dd>:first-child {
margin-top: 0px;
}

dl dd>:last-child {
margin-bottom: 0px;
}

/* CODE
=============================================================================*/

pre, code, tt {
font-size: 12px;
font-family: Consolas, "Liberation Mono", Courier, monospace;
}

code, tt {
margin: 0 0px;
padding: 0px 0px;
white-space: nowrap;
border: 1px solid #eaeaea;
background-color: #f8f8f8;
border-radius: 3px;
}

pre>code {
margin: 0;
padding: 0;
white-space: pre;
border: none;
background: transparent;
}

pre {
background-color: #f8f8f8;
border: 1px solid #ccc;
font-size: 13px;
line-height: 19px;
overflow: auto;
padding: 6px 10px;
border-radius: 3px;
}

pre code, pre tt {
background-color: transparent;
border: none;
}

kbd {
-moz-border-bottom-colors: none;
-moz-border-left-colors: none;
-moz-border-right-colors: none;
-moz-border-top-colors: none;
background-color: #DDDDDD;
background-image: linear-gradient(#F1F1F1, #DDDDDD);
background-repeat: repeat-x;
border-color: #DDDDDD #CCCCCC #CCCCCC #DDDDDD;
border-image: none;
border-radius: 2px 2px 2px 2px;
border-style: solid;
border-width: 1px;
font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
line-height: 10px;
padding: 1px 4px;
}

/* QUOTES
=============================================================================*/

blockquote {
border-left: 4px solid #DDD;
padding: 0 15px;
color: #777;
}

blockquote>:first-child {
margin-top: 0px;
}

blockquote>:last-child {
margin-bottom: 0px;
}

/* HORIZONTAL RULES
=============================================================================*/

hr {
clear: both;
margin: 15px 0;
height: 0px;
overflow: hidden;
border: none;
background: transparent;
border-bottom: 4px solid #ddd;
padding: 0;
}

/* IMAGES
=============================================================================*/

img {
max-width: 100%
}
-->

No.51、在类数组对象上附庸通用的数组方法

Tips:

  1. 对于类数组对象,通过提取方法对象并使用其call方法来复用通用的Array方法
  2. 任意一个具有索引属性和恰当length属性的对象都可以使用通用的Array方法

Array.proteotype中的标准方法被设计成其他对象可复用的方法,即使这些对象没有继承Array。很实际的一个例子就是 arguments ,示例如下:

//define
function fun(){
console.log(arguments); // [1, 2, 3]
console.log(arguments instanceof Array) // false
arguments.forEach(function(argv){ //TypeError
console.log(argv)
});
} //call
fun(1, 2, 3);

从结果来看,输出arguments和数组非常相似,通过instanceof来看,确实不是数组,所以arguments是类数组对象,但是在执行forEach的时候却TypeError。why?

因为 arguments 没有继承Array.prototype,所以并不能直接调用forEach方法,但是可以提取forEach方法的引用并使用其call来调用,代码如下:

//define
function fun(){
[].forEach.call(arguments, function(argv){
console.log(argv);
});
} //call
fun(1, 2, 3);

除了arguments之外,dom的NodeList也是类数组对象:

var nodes = document.getElementsByTagName('a');
console.log(nodes);
console.log(nodes instanceof Array); // false

那么,到底怎样使得一个对象“看起来像数组”呢?有以下两个规则:

  1. 具有一个范围在0到2^32 - 1 的整型length属性
  2. length属性大于该对象的最大索引。索引是一个范围在0到2^32 -2 的整数,它的字符串表示的是该对象的一个key。

鉴于以上规则,那么我们可以自己创建类数组对象:

var arrayLike = {0: 'a', 1: 'b', 2: 'c', length: 3};
var result = [].map.call(arrayLike, function(el){
return el.toUpperCase();
});
console.log(result); // ['A', 'B', 'C']

特例,数组连接方法concat不是完全通用的。因为它会检查对象的[[Class]]属性,要想连接类数组对象,我们就需要先将类数组处理为数组:

var arrLike = {0: 'a', length: 1};
var arr = [].slice.call(arrLike);
console.log(['A'].concat(arr)); // ['A', 'a']

No.52、数组字面量优于数组构造函数

Tips:

  1. 如果数组构造函数的第一个参数是数字则数组的构造函数行为是不同的
  2. 使用数组字面量替代数组构造函数

原因如下:

[] 比 new Array简洁

var arr = [];
var arr = new Array();

使用new Array(),必须要确保没有人重新包转过Array变量

funciton f(Array){
return new Array(1, 2, 3, 4, 5);
}
f(String); //new String(1)

使用new Array(),必须要确保没有人修改过全局的Array变量

Array = String
new Array(1, 2, 3); // new String(1)

使用new Array时,由于第一个参数类型不同,会导致二义性

new Array('hello') 和 ['hello'] 等价
[1] 和 new Array(1) 不等价,前者创建包含元素的1的数组,后则创建长度为1的数组。

所以,优先使用字面量,因为数组字面量具有更规范、更一致的语义。

No.53、保持一致的约定

Tips:

  1. 在变量命名和函数签名中使用一致的约定
  2. 不要偏离用户在他们的开发平台中很可能遇到的约定

有良好的编码习惯,使用业界常规的编码规范,同时注意参数的顺序等。一句话概述:保持代码的一致性

No.54、将undefined看做“没有值”

Tips:

  1. 避免使用undefined表示任何非特定值
  2. 使用描述性的字符串值或命名布尔属性的对象,而不要使用undefined 或 null来代表特定应用标志
  3. 提供参数默认值应该采用测试undefined的方式,而不是检查arguments.length。
  4. 在允许0、NaN或空字符串为有效参数的地方,绝不要通过真值测试来实现参数默认值。

undefined很特殊,当JavaScript无法提供具体的值时没救产生undefined。 如只定义变量,不赋值;或者是对象中不存在属性;再者,函数无return语句都会产生undefined。

var x;
console.log(x); //undefined
var o = {};
console.log(o.p1); //undefined
function fun(){ }
console.log(fun()); //undefined

未给函数参数提供实参则该函数参数值为undefined

function fun(x){
return x;
}
console.log(fun()); //undefined

将undefined看做缺少某个特定的值是公约。将它用于其他目的具有很高的风险:

//假设highlight为设置元素高亮
element.highlight('yellow'); //设置为黄色 //如果要设置为随机颜色
//方式一、如果遇到undefined则设置为随机
element.highlight(undefined); //这样的方式通常会产生歧义
element.highlight(config.highlightColor);
//使用如上语句时,我们的期望一般是没有提供配置则使用默认色,但是由于undefined代表随机,那么破坏了这种常规思维。让代码变得难以理解。 //更好的做法
element.highlight('random');
//或者是
element.highlight({random: true});

另一个提防undefined的地方是可选参数的实现。

function fun(a, b){
if(arguments.length < 2){
b = 'xx';
}
}

如果使用 fun(a);调用,基本符合预期;但是如果使用fun(a, 'undefind');则不会执行if之内的语句,导致结果错误,如果测试是否为undefined有助于打造更为健壮的API。

针对可选参数这个问题,另外一个合理的替代方案是:

function fun(a, b){
b = b || 'xxx';
}

但是要注意,真值测试并不总是安全的。如果一个函数应该接受空字符串,0,NaN为合法值,那么真值测试就不该使用了。

//Bad Use
function Point(x, y){
this.x = x || 200;
this.y = y || 200;
}

以上代码有什么问题呢,因为使用 new Point(0, 0);会导致使用默认值,这样就偏离了预期。所以需要更严格的测试:

function Point(x, y){
this.x = x === undefined ? 200 : x;
this.y = y === undefined ? 200 : y;
}

No.55、接收关键字参数的选项对象

Tips:

  1. 使用选项对象似的API更具可读性、更容易记忆
  2. 所有通过选项对象提供的参数应当被视为可选的
  3. 使用extend函数抽象出从选项对象中提取值的逻辑

首先来看一个复杂的函数调用:

fun(200, 200, 'action', 'green', true);

一眼望去,完全不知所云。在体会到C#的可选参数的便利性的时候,肯定会想JavaScript要是有这样的用法就好了。

幸运的是,JavaScript提供了一个简单、轻量的惯用法:选项对象。基本达到了可选参数的效果。

fun({
width: 200,
height: 200,
action: 'action',
color: 'green',
ignoreError: true
});

相对来说,更繁琐一点,但是更易于阅读。另外一个好处就是,参数都是可选的。

如果有必选参数,那么在设计API的时候。建议将它们独立于选项之外,其他语言也可借鉴这种思路。

// options 为可选参数
function fun(width, height, options){
}

通过extend组合可选参数和默认参数,可以让函数变得简洁和健壮。

function fun(width, height, options){
var defaults = {
color: 'green',
ignoreError: false,
action: ''
}
//$.extend 可以理解为jQuery的方法
options = $.extend({}, defaults, options);
//do something...
}

编写高质量JS代码的68个有效方法(十一)的更多相关文章

  1. 编写高质量JS代码的68个有效方法(八)

    [20141227]编写高质量JS代码的68个有效方法(八) *:first-child { margin-top: 0 !important; } body>*:last-child { ma ...

  2. 编写高质量JS代码的68个有效方法(七)

    [20141220]编写高质量JS代码的68个有效方法(七) *:first-child { margin-top: 0 !important; } body>*:last-child { ma ...

  3. 编写高质量JS代码的68个有效方法(六)

    [20141213]编写高质量JS代码的68个有效方法(六) *:first-child { margin-top: 0 !important; } body>*:last-child { ma ...

  4. 编写高质量JS代码的68个有效方法(四)

    [20141129]编写高质量JS代码的68个有效方法(四) *:first-child { margin-top: 0 !important; } body>*:last-child { ma ...

  5. 编写高质量JS代码的68个有效方法(三)

    [20141030]编写高质量JS代码的68个有效方法(三) *:first-child { margin-top: 0 !important; } body>*:last-child { ma ...

  6. 编写高质量JS代码的68个有效方法(二)

    [20141011]编写高质量JS代码的68个有效方法(二) *:first-child { margin-top: 0 !important; } body>*:last-child { ma ...

  7. JavaScript手札:《编写高质量JS代码的68个有效方法》(一)(1~5)

    编写高质量JS代码的68个有效方法(一) *:first-child { margin-top: 0 !important; } body>*:last-child { margin-botto ...

  8. 编写高质量JS代码的68个有效方法(十三)

    No.61.不要阻塞I/O事件队列 Tips: 异步API使用回调函数来延缓处理代价高昂的操作以避免阻塞主应用程序 JavaScript并发的接收事件,但会使用一个事件队列按序地处理事件处理程序 在应 ...

  9. 编写高质量JS代码的68个有效方法(十)

    *:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: 0 !important; } /* ...

随机推荐

  1. Windows Server 2016 桌面环境的自动配置脚本

    除非学习要求,还是建议使用Windows 10 LTSB 2016或其他桌面系统. github:https://github.com/m2nlight/WindowsServerToWindowsD ...

  2. [1].jekyll扫盲

    一.jekyll是什么? jekyll是一款免费的blog生成工具,将纯文本(plain text)转换为静态网站或博客. Jekyll是一个使用Ruby编写的静态站点生成工具,使用Liquid模板渲 ...

  3. Utopian Tree in Java

    The Utopian tree goes through 2 cycles of growth every year. The first growth cycle occurs during th ...

  4. 努力学习 HTML5 (3)—— 改造传统的 HTML 页面

    要了解和熟悉 HTML5 中的新的语义元素,最好的方式就是拿一经典的 HTML 文档作例子,然后把 HTML5 的一些新鲜营养充实进入.如下就是我们要改造的页面,该页面很简单,只包含一篇文章. Apo ...

  5. mybatis connection error Cannot create PoolableConnectionFactory (Access denied for user 'root '@'local

    org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.exceptions.Persiste ...

  6. windows7文件共享

    工作组模式下: 参考:http://support.microsoft.com/kb/2533010/zh-cn 1.首先区分网络类型配置文件:家庭网络,工作网络还是公用网络 2.每种类型区分两种文件 ...

  7. 【OpenWRT】 Chaos Calmer 15.05 编译

    进入正题,编译环境准备完毕后,下载源码 git clone git://git.coding.net/leop/openwrt.git 复制代码 复制dl包(可以加快初次编译速度,但非必须)链接:pa ...

  8. goldengate一些参数整理

    转自:http://blog.csdn.net/lemontree1123/article/details/46603549 manager参数: AUTOSTART:指定在mgr启动时自动启动那些进 ...

  9. 数据仓库专题(23):总线矩阵的另类应用-Drill Down into a More Detailed Bus Matrix

    一.前言 Many of you are already familiar with the data warehouse bus architecture and matrix given thei ...

  10. linux epoll 开发指南-【ffrpc源码解析】

    摘要 关于epoll的问题很早就像写文章讲讲自己的看法,但是由于ffrpc一直没有完工,所以也就拖下来了.Epoll主要在服务器编程中使用,本文主要探讨服务器程序中epoll的使用技巧.Epoll一般 ...