(五)我的JavaScript系列:JavaScript的糟粕
泪眼问花花不语,乱红飞过秋千去。
JavaScript的糟粕
JavaScript语言是一门集精华与糟粕于一体的语言。在JavaScript: the good parts中,便集中讨论了关于精华与糟粕的主题。有兴趣的同学可以读读这本书,真的不错。基础不错的可以跳过前面的章节,直接进入附录的糟粕与鸡肋的部分。我呢,就先在这本书里列举几个我感兴趣的糟粕部分与大家分享:
全局变量
这恐怕是JavaScript当中最坑的部分了。先且不论全局变量的种种坏处了。在JavaScript中,定义一个全局变量是很轻松的一件事,可以通过下面的三种方式:
在函数外通过var定义:
var foo = value;
绑定到全局对象window:
window.foo = value;
在任何地方不通过var定义变量:
foo = value;
这里的准则就是一般不要在函数外定义变量(即便是通过var),定义变量时一定不能忘记var(但忘记var又是件很常见的错误)。
作用域
JavaScript中的只有全局作用域和函数作用域两种,没有块作用域。同一个函数内的所有变量属于同一个作用域。例如下面的代码,foo的作用域不是if块,而是函数foo,所以在if块之外依然可以访问foo。
function f() {
if(true) {
var foo = 'foo';
}
console.log(foo); //依然可以访问foo
}
所以一种推荐的方式是在函数的顶部声明变量,就像C语言那样做。整个函数看上去就像下面的形式:
function f() {
var a, b, c; //在函数顶部声明函数内使用的所有变量
a = b = c = 2; //然后再使用变量
}
不过,像这样编程是一种很烦的方式。
自动插入分号机制
JavaScript会在每行末尾自动插入一个分号,只要语法允许。例如下面的代码
return
{
status: true
};
会被转化为:
return;
{
status: true
};
但下面的代码却不会(因为插入分号语法上不允许):
return {
status: true
}
所以为了避免理解上的歧义,JavaScript最佳实践建议手动加上分号,而不要依赖语言的自动插入分号机制。不过,现代语言(Ruby、Python等)基本都去掉分号行为了,每行代码都要加上个分号也是个烦人的事。
保留字
JavaScript上定义了很多但压根没用上的保留字,例如:abstract
, boolean
, byte
, int
…
typeof
JavaScript的typeof往往文不对题,例如:
typeof null === 'object'
所以,用到typeof时,往往要多加小心。
浮点数
JavaScript中的数字没有整数类型,只有浮点数类型(实际为IEEE 754,即C语言的double类型)。众所周知,浮点数得到的结果是不精确的。不过好在浮点数表示的整数,它们之间的运算是精确的。
False值
JavaScript中,有很多值能够表示假值:
- 0
- NaN (非数)
- ‘’ (空字符串)
- false
- null
- undefined
所以,在使用if条件判断的时候,要适当注意下。
==
在JavaScript中,有两种形式的等号操作符:==
,===
。其中==
存在坑的地方。它在比较前,会先尝试进行类型转化再去比较。这里的问题在于,类型转化的规则太过复杂了,很难掌握。例如
'' == '0' //false
0 == '' //true
0 == '0' //true
而===
在比较的时候不会进行类型转化,只有类型相同和值相等的两个对象才会返回true。
缺少块符号的语句
块符号,即{}
。在JavaScript中,if
,while
,for
内部的语句需要用大括号括起来。例外的情况是它们下面只有一条语句的时候。
if(ok)
t = true;
不过这不是建议的方式。JavaScript最佳实践要求无论何种情况都要加上大括号,除非它们写在同一行。要么
if(ok) {
t = true;
}
要么
if(ok) t = true;
第二种明显不怎么易看。
new语句
JavaScript的构造器函数需要通过new新建对象。如果忘记new,那它就是一个普通的函数调用,this被绑定到全局对象window。此时是非常危险的。
function Dog(name) {
this.name = name;
}
Dog.prototype.bark = function() {
return 'I am ' + this.name;
}
当调用构造器函数时,千万别漏掉new。JavaScript最佳实践甚至建议不要使用构造器函数,也就是不要通过new来新建对象。它的意思大概是像下面这样新建对象:
function dog(name) {
var dog = {};
dog.bark = function() {
return 'I am ' + name;
}
return dog;
}
这是我以前经常用的一种方式。这里利用闭包的特性将name化为私有变量。一个很明显的缺点是bark函数被定义了多次。
就该被遗忘的特性
下面的一些特性我从来没接触过,据说是坑人的特性。既然这样,我也不要去学习它们了。大家直接忽略它们就可以了。
- with语句
- eval函数
- ++ -- (不要a++,用a+=1替代)
- 位运算符 (& | ^ ~ >> <<)
相关资源
一些推荐的JavaScript学习教程
(五)我的JavaScript系列:JavaScript的糟粕的更多相关文章
- JavaScript 系列--JavaScript一些奇淫技巧的实现方法(二)数字格式化 1234567890转1,234,567,890;argruments 对象(类数组)转换成数组
一.前言 之前写了一篇文章:JavaScript 系列--JavaScript一些奇淫技巧的实现方法(一)简短的sleep函数,获取时间戳 https://www.mwcxs.top/page/746 ...
- JavaScript 系列--JavaScript一些奇淫技巧的实现方法(一)简短的sleep函数,获取时间戳
一.前言 有些东西很好用,但是你未必知道:有些东西你可能用过,但是你未必知道原理.实现一个目的有多种途径,俗话说,条条大路通罗马.发散一下大家的思维以及拓展一下知识面. 二.实现一个简短的sleep函 ...
- JavaScript系列--JavaScript数组高阶函数reduce()方法详解及奇淫技巧
一.前言 reduce() 方法接收一个函数作为累加器,数组中的每个值(从左到右)开始缩减,最终计算为一个值. reduce() 可以作为一个高阶函数,用于函数的 compose. reduce()方 ...
- JavaScript 系列--JavaScript一些奇淫技巧的实现方法(三)数字取整,数组求和
一.前言 简短的sleep函数,获取时间戳:https://www.mwcxs.top/page/746.html 数字格式化 1234567890 --> 1,234,567,890:argr ...
- JavaScript 系列博客(五)
JavaScript 系列博客(五) 前言 本篇博客学习 js 选择器来控制 css 和 html.使用事件(钩子函数)来处理事件完成后完成指定功能以及js 事件控制页面内容. js 选择器 在学习 ...
- (一)我的Javascript系列:Javascript的面向对象旅程(上)
今宵酒醒何处,杨柳岸,晓风残月 导引 我的JavaScript系列文章是我自己对JavaScript语言的感悟所撰写的系列文章.现在还没有写完.目前一共出了下面的系列: (三)我的JavaScript ...
- 汤姆大叔 javascript 系列 第20课 最后的5到javascript题目
博客链接:http://www.cnblogs.com/TomXu/archive/2012/02/10/2342098.html 原题: 大叔注:这些题目也是来自出这5个题目的人,当然如果你能答对4 ...
- 深入理解JavaScript系列(1):编写高质量JavaScript代码的基本要点
深入理解JavaScript系列(1):编写高质量JavaScript代码的基本要点 2011-12-28 23:00 by 汤姆大叔, 139489 阅读, 119 评论, 收藏, 编辑 才华横溢的 ...
- javascript系列之this
原文:javascript系列之this 引言 在这篇文章里我们将会讨论与执行上下文直接相关的更多细节.讨论的主题就是this关键字.实践证明,这个主题是足够难的并且在不同的执行上下文中判定this的 ...
- JavaScript 系列博客(一)
JavaScript 系列博客(一) 前言 本系列博客为记录学习 JavaScript 的学习笔记,会从基础开始慢慢探索 js.今天的学习笔记主要为 js 引入.定义变量以及 JavaScript 中 ...
随机推荐
- [poj1811]Prime Test(Pollard-Rho大整数分解)
问题描述:素性测试兼质因子分解 解题关键:pollard-rho质因数分解,在RSA的破译中也起到了很大的作用 期望复杂度:$O({n^{\frac{1}{4}}})$ #include<cst ...
- SeetaFace教程(一) 在 VS 中的编译安装和环境配置
SeetaFace开源库由FaceDetection.FaceAlignment.FaceIdentification三部分组成.FaceDetection是在一副图片中检测出人脸区域,以一个方形区域 ...
- windows7无法启动Telnet服务,出现…
windows7无法启动Telnet服务,出现错误1068 2012 年 03 月 16 日 在[控制面板--程序--打开或关闭Windows功能]中开启telnet服务器和客户端后,在运行窗口中输入 ...
- ubuntu12.04+virtualbox+winxp的关于摄像头无法使用,声音出不来的问题
前天在ubuntu上安装了个virtualbox的虚拟机.以前在windows下面是用的vmware.结果到了ubuntu下面折腾半天用不了,于是就装了个virtualbox,在virtualbox里 ...
- 快速部署Kubernetes集群管理
这篇文章介绍了如何快速部署一套Kubernetes集群,下面就快速开始吧! 准备工作 //关闭防火墙 systemctl stop firewalld.service systemctl disabl ...
- Infoapth 使用拼写 并加载web part 在Infopath的页面上
<g_vml_:shape style="POSITION: absolute; WIDTH: 568px; HEIGHT: 1312px; TOP: 0px; LEFT: 0px&q ...
- HTML5学习笔记(三)新属性、功能
HTML5 拖放 1.元素的 draggable 属性设置为 true 2.ondragstart 属性调用函数,函数中dataTransfer.setData() 方法设置被拖数据的数据类型和值 3 ...
- C++ STL vector使用总结
vector是C++标准模板库中的部分内容,它是一个多功能的,能够操作多种数据结构和算法的模板类和函数库.vector之所以被认为是一个容器,是因为它能够像容器一样存放各种类型的对象,简单地说vect ...
- 湖南集训day7
难度:☆☆☆☆☆☆ /* 由观察可知 同种颜色的减去他的父亲值相同 我们考虑把询问的两个数分别减去小于它的最大斐波那契数. */ #include<iostream> #include&l ...
- 【微信小程序】开发实战 之 「数据缓存API」解析
每个小程序都可以有自己的本地缓存,可以通过 数据缓存的API 实现对本地缓存进行 设置.获取和清理.本地缓存最大为10M.localStorage是永久存储的,但我们不建议将关键信息都放在localS ...