欢迎大家关注腾讯云技术社区-博客园官方主页,我们将持续在博客园为大家推荐技术精品文章哦~

2016年6月加入腾讯,目前在SNG社交网络质量部从事内部平台工具的研发。熟悉PHP、JS、CSS,喜欢弹吉他。

一、理解JavaScript的浮点数

由IEEE754标准制定,JavaScript中所有的数字都是双精度浮点数,即64位编码数字。
JavaScript大多数的算术运算符可以进行整数、浮点数或者两者的组合进行计算。但是位运算符比较特殊,JavaScript不会直接把操作数作为浮点数进行运算。需要这些步骤完成运算:

1、把操作数8和1转换成32位整数;

2、每一位按位或运算;

3、把结果转换成64位浮点数。比如:

 8 | 1;  //
//000000000000000000000000000001000 | 000000000000000000000000000001001 = 000000000000000000000000000001001

浮点数的计算是不精确的,浮点运算只能四舍五入到最接近的可表示的实数。当执行一系列的运算时,随着舍入误差的积累,运算结果会越来越不精确。比如:

0.1 + 0.2;  //0.30000000000000004
0.1 + 0.2 + 0.3; //0.6000000000000001

加法中的结合律在JavaScript中对于浮点数有时候并不成立:

(0.1 + 0.2) + 0.3;   //0.6000000000000001
0.1 + (0.2 + 0.3); //0.6

小心浮点数,解决其计算不精确的一个简单策略就是将浮点数转换成整数进行运算,整数的运算是精确的,不用担心舍入误差。

二、当心隐式的强制转换

JavaScript中,运算符+既重载了数字相加,又重载了字符串连接操作,这取决于其参数的类型,简单总结如下:

(1)如果两个操作数都是数值,执行常规加法运算

(2)如果有一个操作数是字符串,则将另一个操作数转换成字符串,再进行字符串的拼接

(3)如果有一个操作数是对象、数值或布尔值,如果 toString 方法存在并且返回原始类型,返回 toString 的结果。如果toString 方法不存在或者返回的不是原始类型,调用 valueOf 方法,如果 valueOf 方法存在,并且返回原始类型数据,返回 valueOf 的结果。其他情况,抛出错误。如果是undefined、null、NaN会调用String()函数取得字符串值’undefined’、’null’、’NaN’,再按照情形(2)进行运算

算数运算符-*/、和%在计算之前都会尝试将其参数转换为数字,简单总结如下:

(1)如果两个操作数都是数值,执行常规运算

(2)如果有一个数是NaN,则结果是NaN

(3)如果有一个操作数字符串、布尔值、null或undefined,则先调用Number()方法将其转换为数值,再进行运算

(4)如果有一个操作数是对象,如果 valueOf 存在,且返回原始类型数据,返回 valueOf 的结果。如果 toString 存在,且返回原始类型数据,返回 toString 的结果。其他情况,抛出错误。再按照上面规则进行运算。

因此,valueOf()toString()方法应该被同时重写,并返回相同的数字字符串或数值表示,才不至于强制隐式转换时得到意想不到的结果。
  
逻辑运算符||&&可以接受任何值作为参数,会将参数隐式的强制转换成布尔值。JavaScript中有6个假值:false、0、“”、NaN、null和undefined,其他所有的值都为真值。因此在函数中判断参数是否是undefined不能简单的使用if,而应该使用typeof:

function isUndefined(a){
if (typeof a === 'undefined'){ //或者a === undefined
console.log('a is not defined')
}
}

三、避免对混合类型使用==运算符

"1.0e0" == {valueOf: function(){return true}};   //true

相等操作符==在比较两个参数时会参照规则进行隐式转换,判断两个值是否相等,使用全等操作符===是最安全的。j简单总结一下==的隐式转换规则:

四、尽量少用全局对象,始终声明局部变量

定义全局变量会污染共享的公共命名空间,可能导致意外的命名冲突,不利于模块化,导致程序中独立组件间的不必要耦合。全局变量在浏览器中会被绑定到全局的window对象,添加或修改全局变量会自动更新全局对象,更新全局对象也会自动更新全局全局命名空间。

window.foo;  //undefined
var foo = 'global foo';
window.foo; //"global foo"
window.foo = 'changed'
foo; //changed

JavaScript会把没有使用var声明的变量简单地当做全局变量,如果忘记声明局部变量,改变量会被隐式地转变成全局变量。任何时候都应该使用var声明局部变量。

function swap(array, i, j){
var temp = a[i]; //使用var声明局部变量,否则temp会变成全局变量
a[i] = a[j];
a[j] = temp;
}

五、理解变量提升

JavaScript不支持块级作用域,变量定义的作用域并不是离其最近的封闭语句或代码块,而是包含它们的函数。来看一个例子。

function test(params) {
for(var i = 0; i < 10; i++){
var params = i;
}
return params;
}
test(20); //

在for循环中声明了一个局部变量params,由于JavaScript不支持块级作用域,params重新声明了函数参数params,导致最后的结果并不是我们传进去的值。

理解JavaScript变量声明需要把声明变量看作由声明和赋值两部分组成。JavaScript隐式地提升声明部分到封闭函数的顶部,而将赋值留在原地。也就是变量的作用域是整个函数,在=语句出现的位置进行赋值。下面第一种方式会被JavaScript隐式地提升声明部分,等价于第二种方式那样。建议手动提升局部变量的声明,避免混淆。

function f() {                              function f() {
/*do something*/ var x;
//... //...
{ {
//... //...
var x = /*...*/ x = /*...*/
//... //...
} }
} }

JavaScript没有块级作用域的一个例外是异常处理,try-catch语句将捕获的异常绑定到一个变量,该变量的作用域只是catch语句块。下面的例子中catch语句块中的x值的改变并没有影响最初声明的x的值,说明该变量的作用域只是catch语句块。

function test(){
var x = 'var', result = [];
result.push(x);
try{
throw 'exception';
} catch(x){
x = 'catch';
}
result.push(x);
return result;
}
test(); //["var", "var"]

六、熟练掌握高阶函数

  高阶函数是那些将函数作为参数或返回值的函数,是一种更为抽象的函数。函数作为参数(其实就是回调函数)在JavaScript中被大量使用:

[3,2,1,1,4,9].sort(function(){
if(x < y){
return -1;
}
if(x > y){
return 1;
}
return 0;
}); //[1,1,2,3,4,9] var name = ['tongyang', 'Bob', 'Alice'];
name.map(function(name){
return name.toUpperCase();
}); //['TONGYANG', 'BOB', 'ALICE']

学会使用高阶函数通常可以简化代码并消除繁琐的样板代码,如果出现重复或者相似的代码,我们可以考虑使用高阶函数。

var aIndex = "a".charCodeAt(0);   //
var alphabet = "";
for(var i = 0; i < 26; ++i){
alphabet += String.fromCharCode(aIndex + i)
}
alphabet; //"abcdefghijklmnopqrstuvwxyz" var digits = "";
for(var i = 0; i < 10; ++i){
digits += i;
}
digits; // var random = "";
for(var i = 0; i < 8; ++i){
random += String.fromCharCode(Math.floor(Math.random() * 26) + aIndex);
}
random; //atzuvtcz

这三段代码有相同的基本逻辑,按照特定的规则拼接字符串。我们使用高阶函数来重写这段代码

function buildString(number, callback){
var result = "";
for(var i = 0; i < number; ++i){
result += callback(i);
}
return result;
} var aIndex = "a".charCodeAt(0); //
var alphabet = buildString(26, function(i){
return String.fromCharCode(aIndex + i);
});
var digits = buildString(10, function(i){
return i;
});
var random = buildString(8, function(){
return String.fromCharCode(Math.floor(Math.random() * 26) + aIndex);
});

相比之下,高阶函数更简捷,逻辑更清晰,掌握高阶函数会提高代码质量,这需要多读优秀的源码,多在项目中实践才能熟练的掌握。

七、在类数组对象上复用通用的数组方法

Array.prototype中的标准方法被设计成其他对象可复用的方法,即使这些对象没有继承Array。

在JavaScript中很常见的类数组对象是DOM中的NodeList。类似document.getElementsByTagName这样的操作会查询Web页面中的节点,并返回NodeList作为搜索的结果。我们可以在NodeLIst对象上面使用通用的数组方法,比如forEach、map、filter。

scriptNodeList = document.getElementsByTagName('script');
[].forEach.call(scriptNodeList, function(node){
console.log(node.src);
});

类数组对象有两个基本特征:

(1)具有一个整形length属性

(2)length属性大于该对象的最大索引。索引是一个整数,它的字符串表示的是该对象中的一个key

可以用一个对象字面量来创建类数组对象:

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

字符串也可以使用通用的数组方法

var result = [].map.call("abc", function(s){
    return s.toUpperCase();
}); //["A", "B", "C"]

只有一个Array方法不是通用的,即数组连接方法concat。这个方法会检查参数的[[Class]]属性。如果参数是一个真实的数组,则会将该数组的内容连接起来作为结果;否则,参数将以一个单一的元素来连接.

function namesColumn() {
return ["Names"].concat(arguments);
}
namesColumn('tongyang', 'Bob', 'Frank'); //["Names", Arguments[3]]

可以使用slice方法来达到我们的目的

function namesColumn() {
return ['Names'].concat([].slice.call(arguments));
}
namesColumn('tongyang', 'Bob', 'Frank'); /*["Names", "tongyang", "Bob", "Frank]*/

在类数组对象上复用通用的数组方法可以极大的减少冗余代码,提高代码质量

欢迎加入QQ群:374933367,与腾云阁原创作者们一起交流,更有机会参与技术大咖的在线分享!

相关阅读

Kotlin Native 详细体验,你想要的都在这儿
Java 程序员快速上手 Kotlin 11招
JavaScriptCore全面解析 (上篇)


此文已由作者授权腾讯云技术社区发布,转载请注明文章出处
原文链接:https://www.qcloud.com/community/article/560964
获取更多腾讯海量技术实践干货,欢迎大家前往腾讯云技术社区

编写高质量的JavaScript代码(一)的更多相关文章

  1. 如何编写高质量的Javascript代码

    1.避免全局变量,因为全局变量容易发生名称上的冲突,可维护性不好. a,使用命名空间 b,使用闭包 c,在函数内部使用var声明 2.编写可维护的代码 a.可读性 b.连续性 c.预见性 d.看起来是 ...

  2. 高质量的javascript代码 -- 深入理解Javascript

    一. 编写高质量的javascript代码基本要点a) 可维护的代码(Writing Maintainable Code)i. 可读(注释)ii. 一致(看上去是同一个人写的)iii. 已记录b) 最 ...

  3. HTML Inspector – 帮助你编写高质量的 HTML 代码

    HTML Inspector 是一款代码质量检测工具,帮助你编写更优秀的 HTML 代码.HTML Inspector 使用 JavaScript 编写,运行在浏览器中,是最好的 HTML 代码检测工 ...

  4. iOS应用开发最佳实践系列一:编写高质量的Objective-C代码

          本文由海水的味道编译整理,转载请注明译者和出处,请勿用于商业用途! 点标记语法 属性和幂等方法(多次调用和一次调用返回的结果相同)使用点标记语法访问,其他的情况使用方括号标记语法. 良好的 ...

  5. 编程精粹--编写高质量C语言代码(3):自己设计并使用断言(二)

    接着上一遍文章<<编程精粹--编写高质量C语言代码(2):自己设计并使用断言(一)>>,继续学习怎样自己设计并使用断言,来更加easy,更加不费力地自己主动寻找出程序中的错误. ...

  6. 如何写出高质量的JavaScript代码

    优秀的Stoyan Stefanov在他的新书中(<Javascript Patterns>)介绍了很多编写高质量代码的技巧,比如避免使用全局变量,使用单一的var关键字,循环式预存长度等 ...

  7. 如何编写高质量的js代码--底层原理

    转自: 如何编写高质量的 JS 函数(1) -- 敲山震虎篇   本文首发于 vivo互联网技术 微信公众号 链接:https://mp.weixin.qq.com/s/7lCK9cHmunvYlbm ...

  8. 怎样编写高质量的java代码

    代码质量概述     怎样辨别一个项目代码写得好还是坏?优秀的代码和腐化的代码区别在哪里?怎么让自己写的代码既漂亮又有生命力?接下来将对代码质量的问题进行一些粗略的介绍.也请有过代码质量相关经验的朋友 ...

  9. 怎样编写高质量的 Java 代码

    代码质量概述 怎样辨别一个项目代码写得好还是坏?优秀的代码和腐化的代码区别在哪里?怎么让自己写的代码既漂亮又有生命力?接下来将对代码质量的问题进行一些粗略的介绍.也请有过代码质量相关经验的朋友提出宝贵 ...

随机推荐

  1. Knockoutjs:Component and Custom Elements(翻译文章)

    Knockoutjs 的Components 是一种自定义的组件,它以一种强大.简介的方式将你自己的ui代码组织成一种单独的.可重用的模块,自定义的组件(Component)有以下特点: 1.可以替代 ...

  2. 多边形剪裁img

    <!DOCTYPE html><html><head> <meta charset="utf-8"/> <title>& ...

  3. ceph集群安装

    所有 Ceph 部署都始于 Ceph 存储集群.一个 Ceph 集群可以包含数千个存储节点,最简系统至少需要一个监视器和两个 OSD 才能做到数据复制.Ceph 文件系统. Ceph 对象存储.和 C ...

  4. input 点击链接事件

  5. 学习Jammendo代码的心路历程(一)简单的淡出效果实现

    最近在看 Jammendo代码,打算将学习过程简单的记录下来,下面开始第一篇: 打开Jammendo运行之后,出弹出一个对话框,跳过对话框之后,会有一个淡出界面跳转到首页效果的实现.那么这个效果是怎么 ...

  6. oracle查询每个表所占的空间

    查看当前用户的每个表所占的空间大小: select segment_name,sum(bytes)/1024/1024 size_M from user_extents group by segmen ...

  7. reactjs点滴记录

    reactjs: render方法后面,}后面,不要加分号,加逗号,因为是对属性赋值,否则报错: var Test = React.createClass({ render:function(){re ...

  8. UILabel的讲解

    首先,我先自定义几个名词,方便接下来的讲解工作.如下图所示: 接下来,通过五个方面来讲解我们能对UILabel做出哪些改变或者称之为设置: 1.文字 1.1普通文字:内容text.字体大小font.字 ...

  9. 非负矩阵分解(1):准则函数及KL散度

    作者:桂. 时间:2017-04-06  12:29:26 链接:http://www.cnblogs.com/xingshansi/p/6672908.html 声明:欢迎被转载,不过记得注明出处哦 ...

  10. 给 Java 学习者的超全教程整理

    Java 在编程语言排行榜中一直位列前排,可知 Java 语言的受欢迎程度了. 网上有很多 Java 教程,无论是基础入门还是开发小项目的教程都比比皆是,可是系统的很少,对于Java 学习者来说找到系 ...