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

*: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.1、了解你使用的JavaScript版本

Tips:

  1. 决定你的应用程序支持JavaScript的哪些版本。
  2. 确保你使用的任何JavaScript的特性对于应用程序将要运行的所有环境都是支持的。
  3. 总是在执行严格模式检查的环境中测试严格代码。
  4. 当心连接那些在不同严格模式下有不同预期的脚本。

JavaScript的普及使得它在1997年成为国际标准,官方名称为ECMAScript。除了ECMAScript标准存在多个版本之外,还存在一些JavaScript实现支持非标准特性,其他JavaScript实现不支持的情况。所以需要注意你所写的JavaScript代码所支持的版本。

/*[Sample]如下代码,在IE下会Syntax error,但是在Chrome中则是定义常量*/
const PI=3.14;PI=3;PI

由于JavaScript的主要生态系统--Web浏览器并不支持让程序员指定某个JavaScript版本来执行代码。在ES5中,引入了另外一种版本控制的考量--严格格式(strict mode),这个特性允许你选择在受限制的JavaScript版本中禁用JavaScript语言中问题较多或易于出错的特性。由于JS语法涉及向后兼容,所以在没有严格检查的环境中也能执行严格代码。

/*[Sample]如何使用严格模式,在程序/函数体的开始处加入'use strict'
使用字符串字面量作为指令看起来比较怪异,但好处是可以向后兼容,因为执行字符串字面量没有任何副作用
/*
function f(x){
'use strict';
var arguments=[];//SyntaxError:Unexpected eval or arguments in strict mode
}

"use strict"指令只有在脚本或者函数顶部才生效,这也是使用严格模式的一个陷进。脚本连接将变得颇为敏感。假如有多个js文件,一些需要执行在严格模式下,一些不需要执行在严格模式下,如何处理呢?

  1. 将需要严格模式检查的文件和不需要严格模式检查的文件分开连接
  2. 通过将自身包裹在立即调用的函数表达式中的方式来连接多个文件

/*file1.js*/
function fun1(){
var arguments=[];
} /*file2.js*/
'use strict';
function fun2(){
console.log('strict mode!');
} /*按照方式二连接后的文件内容应该是*/
/*fileMerge.js*/
(function(){
function fun1(){
var arguments=[];
}
})();
(function(){
'use strict';
function fun2(){
console.log('strict mode!');
}
})();

No.2、理解JavaScript的浮点数

Tips:

  1. JavaScript的数字都是双精度的浮点数。
  2. JavaScript的整数仅仅是双精度浮点数的一个子集,而不是一个单独的数据类型。
  3. 位运算将数字视为32位的有符号整数。
  4. 当心浮点运算中的精度陷进。

大部分语言都有几种数值数据类型,但是JavaScript只有一种

typeof 1;    //'number'
typeof 1.1; //'number'
typeof -1; //'number'

对于位运算,JavaScript不会直接将操作数作为浮点数运算,会先转换为32位整数再进行运算

8|1;    //9
8.1|1; //9

如何快速从10进制转换到2~36进制?

(100).toString(2);    //1100100
(100).toString(10); //100
(100).toString(35); //2u
(100).toString(36); //2s

注意parseInt和parseFloat的用法

警告(以下为非标准特性,各浏览器执行有差异):

  1. 如果要转换的字符串已0x或者0X开头,那么parseInt('0xAB')等价于parseInt('0xAB',16)
  2. 如果遇到0开头,那么parseInt('013')等价于parseInt('013',8)
  3. 强烈建议在使用parseInt时指定进制

parseInt('9x');    //9 会自动忽略不能转换的字符
parseInt('x9'); //NaN 发现第一个字符就不能转换,返回NaN
parseInt('1100100',2); //100 可以在parseInt的第二个参数指定当前字符串的进制
parseInt('2xxx',2); //NaN 遇到无法转换的情况,返回NaN
parseInt('08'); //IE下:0,Chrome35下:8

浮点数是出了名的不精确,你能知道以下代码的执行结果吗?

0.1+0.2;           //0.30000000000000004
(0.1+0.2)+0.3; //0.6000000000000001
0.1+(0.2+0.3); //0.6
0.3-0.2; //0.09999999999999998

当我们关心精度时,要小心浮点数的局限性。有效的方法是尽可能的采用整数值运算,整数在运算时不需要舍入。

No.3、当心隐式的强制转换

Tips:

  1. 类型错误可能被隐式的强制转换所隐藏。
  2. 重载的运算符+是进行加法运算还是字符串连接取决于其参数类型。
  3. 对象通过valueOf方法强制转换为数字,通过toString方法强制转换为字符串。
  4. 具有valueOf方法的对象应该实现toString方法,返回一个有valueOf方法产生的数字的字符串表示。
  5. 测试一个值是否为未定义的值,应该使用typeof或者与undeined进行比较而不是使用真值运算。

3+true;   //4 true转换为数字1
'fun'(1); //TypeError:string is not a function
null.x; //TypeError: Cannot read property 'x' of null
2+3; //5
2+'3'; //'23' 偏爱字符串,遇到字符串,那么优先用字符串连接
1+2+'3'; //'33' 加法运算是从左到右,所以等价于(1+2)+'3'
1+'2'+3; //'123'
'17'*3; //51
'8'|'1' //9

如何测试一个值是NaN?

var x=NaN;
x===NaN; //false,NaN不等于自身

如果知道带测试的值是数字,那么可以使用标准库函数isNaN

isNaN(NaN);  //true

但是对于其他绝对不是NaN,但会被强制转换为NaN的值,使用isNaN方法是无法区分的。

isNaN('foo');  //true
isNaN(undefined); //true
isNaN({}); //true
isNaN({valueOf:'foo'}); //true

幸运的是,有一个既简单有可靠但有点不直观的方法测试它:

JS中,NaN是唯一一个不等于其自身的值。

var x=NaN;
x!==x //true /*测试x是否是NaN,是返回true,否则返回false*/
function isReallyNaN(x){
return x!==x;
}

如何控制对象的强制转换?

'J'+{toString:function(){return 'S'}};  //'JS'
2*{valueOf:function(){return 3;}}; //6 var obj={
toString:function(){
return '[object Obj]';
},
valueOf:function(){
return 1;
}
}
'object:'+obj; //'object:1' 解释:
1. 在需要数字的场合,优先判断valueOf,没有的话,则采用toString。
2. 如果对象同时拥有valueOf和toString方法,同时又一定是需要数字的场合,那么JavaScript盲目的选择valueOf方法而不是toString方法来解决这种含糊的情况。
3. 针对2:最好避免使用valueOf方法,除非对象的确需要一个数字的抽象,并且obj.toString()能产生一个obj.valueOf()的字符串的表示。

关于真值运算:

JavaScript中有7个假值:false、0、-0、''、NaN、null和undefined,其他都为真值

No.4、原始类型优于封装对象

Tips:

  1. 当做相等比较是,原始类型的封装对象与其原始值行为不一样。
  2. 获取和设置原始类型值的属性会隐式地创建封装对象。

除了对象以外,JavaScript有5个原始值类型:布尔值、数字、字符串、null和undefined。(令人困惑的是,对于null类型进行typeof操作得到的结果为"object",然而,ECMAScript标准描述其为一个独特的类型。)

var s='hello';
var sObj=new String(s);
typeof s; //'string'
typeof sObj; //'object' 包装对象的类型是object var sObj1=new String(s);
var sObj2=new String(s);
sObj1==sObj2; //false
sObj1===sObj2; //false 解释:可以理解为引用类型,每个对象是单独的对象,其引用是不一致的,所以只等于自身。

JavaScript对基本类型有隐式封装,所以我们可以如下书写代码:

'test'.toUpperCase(); //'TEST'

'test'.test='test';
'test'.test; //undefined 解释:对基本类型调用方法/设置属性时,会产生隐式封装。
原始值->封装类型(产生封装对象)->封装对象执行方法/设置属性->返回原始值->抛弃封装对象。
所以更新封装不会造成持久的影响,同时对原始值设置属性是没有意义的。

No.5、避免对混合类型使用==运算符

Tips:

  1. 当参数类型不同时,==运算符应用了一套难以理解的隐式强制转换规则。
  2. 使用===运算符,使读者不需要设计任何的隐式强制转换就能明白你的比较运算。
  3. 当比较不同类型的值时,使用你自己的显式强制转换使程序的行为更清晰。

看代码:

'1.0e0'=={valueOf:function(){return true;}}; //true 因为通过隐式转换,就变成了1==1,所以结果为true。

转换为字符串:''+1; //'1'
转换为数字 : +'1'; //1 var date=new Date('1999/12/31');
date=='1991/12/31';//false
date=='Fri Dec 31 1999 00:00:00 GMT+0800 (China Standard Time)';//true 解释:世界上有太多的数据表现形式,JS需要知道你使用的是哪一种,==运算符并不能推断和统一所有的数据格式,所以更好的策略是显式自定义应用程序转换的逻辑,并使用严格相等运算符。

JavaScript手札:《编写高质量JS代码的68个有效方法》(一)(1~5)的更多相关文章

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

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

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

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

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

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

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

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

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

    [20141129]编写高质量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. 编写高质量JS代码的68个有效方法(十三)

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

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

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

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

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

随机推荐

  1. JS_Ajax基础

    一:Ajax ajax 的全称是Asynchronous(异步) JavaScript and XML 在不刷新页面的情况下从服务器获取,提交数据的一种数据交互方式; 二:Ajax使用步骤概括 //1 ...

  2. 深入理解.NET程序的原理 谈一谈破解.NET软件的工具和方法

    最近一段时间不忙,闲下来的空闲时间,重读了一下CLR的原理,回味一下有关程序集的的知识,顺便练了一下手,学习致用,破解了若干个.NET平台的软件.以此来反观.NET程序开发中,需要注意的一些问题. 基 ...

  3. 我所理解的JavaScript闭包

    目录 一.闭包(Closure) 1.1.什么是闭包? 1.2.为什么要用闭包(作用)? 1.2.1.保护函数内的变量安全. 1.2.2.通过访问外部变量,一个闭包可以暂时保存这些变量的上下文环境,当 ...

  4. Android带多选功能的PhotoPicker

    最近利用闲碎的一些时间开发了一个Android库PhotoPicker,前面一篇文章也介绍了,Android高仿微信图片选择功能的PhotoPicker,之前没有加入选择多张图片的功能,现在加上之后一 ...

  5. CCNA实验1.port-security

    一, 二,MAC地址绑定 3550-1#conf t3550-1(config)#int f0/13550-1(config-if)#switchport mode access /指定端口模式.35 ...

  6. Scala access modifiers and qualifiers in detail

    来自:http://www.jesperdj.com/2016/01/08/scala-access-modifiers-and-qualifiers-in-detail/ Just like Jav ...

  7. Android--使用Canvas绘图

    前言 除了使用已有的图片之外,Android应用常常需要在运行时根据场景动态生成2D图片,比如手机游戏,这就需要借助于Android2D绘图的支持.本篇博客主要讲解一下Android下使用Canvas ...

  8. netsh-winsock-reset;ping的通公网IP和DNS地址和内网网关,就是不能解析域名;

    winXP cmd-------------> netsh winsock reset ============= 相关知识: netsh winsock reset命令含义是重置 Winsoc ...

  9. Android Studio 中关于NDK编译及jni header生成的问题

    之前由于工作原因使用grails这个基于groovy的框架做项目,对groovy感觉很好. 基于groovy的gradle构建系统对我而言自然也是好的没得说. Android Studio 正式版出来 ...

  10. 可能 delphi7 下稳定的最后一版本 GDIPLUS

    可能 delphi7 下稳定的最后一版本 GDIPLUS 万一的 blog 说"终于, Delphi XE2 携带 GDI+ 库了 使用了较早的 http://www.progdigy.co ...