读《编写可维护的JavaScript》第八章总结
第八章 避免“空比较”
我们在对传进来的参数做处理之前,肯定需要验证一下是否是我们想要的,也就是说大多数情况下,我们需要对比一下它的类型。
作者首先给了一个看起来都感觉不对的代码:
var Controller = {
process: function(items) {
if (items !== null) {
items.sort(); // 不好的写法
items.forEach(function(){
// 执行一些逻辑
});
}
}
};
在这段代码中,process()方法显然希望items是一个数组,因为我们看到items拥有sort()和 forEach()。
但是这种写法有很大的问题:items值可以是1,也可以是字符串,甚至可以是对象,这些值都和null不相等,进而导致后面执行process()会出现问题。所以接下来就是各种检测:
8.1 检测原始值
在JavaScript中有5种原始类型: 字符串、数字、布尔值、undefined和null。如果你想检测他们,最佳的办法是使用typeof运算符。(作者推荐: typeof variable这样的用法,这样写也行:typeof(variable),但是看起来像一个函数而不是运算符 )。
基本用法:
- 对于字符串, typeof返回"string"。
- 对于数字,typeof返回"number"。
- 对于布尔值,typeof返回"boolean"。
- 对于undefined,typeof返回"undefined"。
// 检测字符串
if (typeof name === "string") {
anotherName = name.substring(3);
} // 检测数字
if (typeof count === "number") {
updateCount(count);
} // 检测布尔值
if (typeof found === "boolean" && "found") {
message("Found!");
} // 检测undefined
if (typeof MyApp === "undefined") {
MyApp = {
//其他的代码
}
}
typeof运算符的独特之处在于,将其用于一个未声明的变量和值也不会报错,他们都将通过typeof返回"undefined"。
最后一个原始值:null。如果我们所期待的值真的是null,则可以和null进行比较:
// 如果你真的需要检测null,则使用这种方法
var element = document.getElementById("my-div");
if (element !== null) {
element.classname = "found";
}
这里如果DOM元素不存在,则通过document.getElementById()得到的是值为null,这个方法要么返回一个节点,要么返回null。由于这时null是可预见的一种输出,则可以使用!==来检测返回结果。
运行typeof null 则返回"object", 这是一种低效的判断null的方法, 如果你需要检测null,则直接使用恒等运算符(===)或非恒等运算符(!==)。
8.2 检测引用值
引用值也称作对象(object)。JS中除了原始值之外的值都是引用。有这样几种内置的引用函数: Object、Array、Date和Error,数量不多。
typeof运算符在判断这些引用类型时显得力不从心,因为所有对象都返回"object"。
检测某个引用值的类型最好方法是使用instanceof运算符。instanceof的基本语法是:value instanceof constructor。
// 检测日期
if (value instanceof Date) {
console.log(value.getFullYear());
} // 检测正则表达式
if (value instanceof RegExp) {
if (value.test(anotherValue)) {
console.log("Mathes");
}
} // 检测Error
if (value instanceof Error) {
throw value;
}
instanceof的一个很有意思的特性是它不仅检测构造这个对象的构造器,还检测原型链。因为每个对象都继承自Object,因此每个对象的 value instanceof Object都返回true。
var now = new Date();
console.log(now instanceof Object); // true
console.log(now instanceof Date); // true
因为这个原因, instanceof 来判断对象是否属于某个特定类型的做法并非最佳。
接下来作者谈到 :检测自定义类型最好的做法是使用instanceof运算符。也是唯一的办法:
function Person(name) {
this.name = name;
}
var me = new Person("Nicholas");
console.log(me instanceof Object); // true
console.log(me instanceof Person); // true
作者后来又补充了一个我没看懂的限制,在此先记下:
这有个严重的限制:假设一个浏览器帧(frame A) 里的一个对象被传入到另一个帧(frame B)中。俩个帧里都定义了构造函数Person。如果来自帧A的对象是帧A的Person的实例,则如下规则成立:
// true
frameAPersonInstance instanceof frameAPerson // false
frameAPersonInstance instanceof frameBPerson因为每个帧(frame)都拥有Person的一份拷贝,它被认为是该帧中的Person的拷贝的实例,尽管俩个定义可能完全一样的。
在最后,作者说明这种问题也出现在其他俩个非常重要的内置类型:函数和数组。对于他们,一般用不着使用instanceof。
8.2.1 检测函数
对于检测函数:最好的方法是使用typeof,因为它可以跨帧(frame)使用:
function myFunc() { } // 好的写法
console.log(typeof myFunc === "function"); // true
作者又补充- -(这次是因为IE):用typeof来检测函数有一个限制。在IE8和更早期的版本的IE浏览器中,用时typeof来检测DOM节点(比如document.getElementById())中的函数都返回"object"而不是"function"。
// IE8及其更早版本的IE
console.log(typeof document.getElementById); // "object"
console.log(typeof document.createElement); // "object"
console.log(typeof document.getElementsByTagName); // "object"
这个问题是早期IE遗留的问题,开发者往往通过in运算符来检测DOM的方法:
// 检测DOM方法
if ("querySelectorAll" in document) {
images = document.querySelectorAll("img");
}
这段代码检查querySelectorAll是否定义在了document中,如果是,则是用这个方法。尽管不是最理想的的方法,如果想在IE8 及更早的浏览器中检测DOM方法是否存在,这是最安全的做法。在其他所有情形,typeof运算符是检测JavaScript函数的最佳选择。
8.2.2 检测数组
ECMAScript5将Array.isArray()正式引入JavaScript。唯一的目的就是准确的检测一个值是否为数组。
适用于(IE9+、Safari5、Opera 10.5+和Chrome)都实现了Array.isArrary()方法。
在此之前,有一个优雅的解决方案:
function isArray(value) {
return Object.prototype.toString.call(value) === "[object Array]";
}
将这俩方法合并,多数类库都类似的实现了这个方法:
function isArray(value) {
if (typeof Array.isArray === "function") {
return Array.isArray(value);
} else {
return Object.prototype.toString.call(value) === "[object Array]";
}
}
8.3 检测属性
判断属性的最好的方法是使用in运算符。in运算符仅仅会简单地判断属性是否存在,而不会去读属性的值。
之前第三章也说过:in运算符会遍历原型链。如果你只想遍历实例对象,用hasOwnProperty()
所有继承自Object的JavaScript对象都有这个方法。
作者补充到一个例外(又是IE。。醉):在IE8和更早的版本中,DOM对象并非继承自Object,因此也不包含这个方法。所以,你在调用DOM对象的hasOwnProperty()方法之前应当先检测其是否存在(假如你已经知道对象不是DOM。这步可以省略)。
// 对于所有非DOM对象来说,这是好的写法
if (object.hasOwnProperty("realted")) {
// 执行这里的代码
} // 如果你不确定是否为DOM对象,则可以这样写
if ("hasOwnProperty" in object && object.hasOwnProperty("related")) {
// 执行这里的代码
}
读《编写可维护的JavaScript》第八章总结的更多相关文章
- [已读]编写可维护的javascript
13年4月份出版,作者是大名鼎鼎的Zakas,他的另两本书<javascript高级程序设计>与<高性能javascript>你一定听过或者读过. 这本书重点讲了编码风格和编码 ...
- 【读书笔记】读《编写可维护的JavaScript》 - 编程实践(第二部分)
本书的第二个部分总结了有关编程实践相关的内容,每一个章节都非常不错,捡取了其中5个章节的内容.对大家组织高维护性的代码具有辅导作用. 5个章节如下—— 一.UI层的松耦合 二.避免使用全局变量 三.事 ...
- 拯救一切强迫症 - 读《编写可维护的 JavaScript》(一)
拯救一切强迫症 - 读<编写可维护的 JavaScript>(一) 本文写于 2020 年 4 月 24 日 我在小学的时候就有接触过编程,所以读大一的时候 C 语言还算是轻车熟路.自然会 ...
- 《编写可维护的javascript》读书笔记(上)
最近在读<编写可维护的javascript>这本书,为了加深记忆,简单做个笔记,同时也让没有读过的同学有一个大概的了解. 一.编程风格 程序是写给人读的,所以一个团队的编程风格要保持一致. ...
- 编写可维护的JavaScript 收纳架
如果你看过Nicolas C.Zakas写过的任何作品,你必须承认他是个不折不扣的天才.也只有天才级的才能写出<JavaScript高级程序设计>让所有的前端攻城师人手一本.Nicolas ...
- 推荐一本好书:编写可维护的JavaScript(可下载)
目录 推荐一本好书:编写可维护的JavaScript(可下载) 书摘: 下载: 有些建议: 推荐一本好书:编写可维护的JavaScript(可下载) 书摘: 很多设计模式就是为了解决紧耦合的问题.如果 ...
- 《编写可维护的JavaScript》之编程实践
最近读完<编写可维护的JavaScript>,让我受益匪浅,它指明了编码过程中,需要注意的方方面面,在团队协作中特别有用,可维护性是一个非常大的话题,这本书是一个不错的起点. 本书虽短,却 ...
- 编写可维护的Javascript读书笔记
写在前面:之前硬着头皮参加了java方面的编程规范培训,收货良多,工作半年有余的时候,总算感觉到一丝丝Coding之美,以及造轮子的乐趣,以至于后面开发新功能的时候,在Coding style方面花了 ...
- 《编写可维护的javascript》读书笔记(中)——编程实践
上篇读书笔记系列之:<编写可维护的javascript>读书笔记(上) 上篇说的是编程风格,记录的都是最重要的点,不讲废话,写的比较简洁,而本篇将加入一些实例,因为那样比较容易说明问题. ...
- 编写可维护的JavaScript之编程风格
在团队中只有每个人的编程风格一致,大家才能方便的互相看懂和维护对方的代码. 1. 层级缩进 对于层级缩进目前有两种主张:1)使用制表符这种方法有两种好处,第一,制表符和缩进层级之间是一一对应关系,符合 ...
随机推荐
- TIJ——Chapter Seven:Reusing Classes
Reusing Classes 有两种常用方式实现类的重用,组件(在新类中创建存在类的对象)和继承. Composition syntax Every non-primitive object has ...
- FreeBSD 查看硬件信息
systat 能实时查看各种信息 systat -pigs 默认值CPU systat -iostat 硬盘IO systat -swap 交换分区 systat -mbufs 网络缓冲区 systa ...
- c++减法高精度算法
c++高精度算法,对于新手来说还是一大挑战,只要克服它,你就开启了编程的新篇章,算法. 我发的这个代码并不是很好,占用内存很多而且运行时间很长(不超过0.02秒),但是很好理解,很适合新手 高精算法的 ...
- python staticmethod and classmethod方法
静态方法无绑定,和普通函数使用方法一样,只是需要通过类或者实例来调用.没有隐性参数. 实例方法针对的是实例,类方法针对的是类,他们都可以继承和重新定义,而静态方法则不能继承,可以认为是全局函数. #h ...
- Mac下搭建git
一.在本地git库中添加用户名及邮箱 git config --global user.name "username" git config --global user.email ...
- C++预定义字符函数
利用 get 成员函数可读取文件中的一切字符,包括空白字符.文件结尾.用 >> 读取文件,会自动忽略空白字符(空格.换行符.制表符) C++ 预定义的字符函数(均在 cctype 库中定义 ...
- tslib1.4编译
准备工作:ubuntu14.04-64位+arm-linux-gcc(2014)+tslib.14 1.arm-linux-gcc下载地址:http://www.veryarm.com/arm-non ...
- WebService "因 URL 意外地以 结束,请求格式无法识别" 的解决方法
最近在做一个图片上传的功能,js调用用webservice进行异步访问服务器,对于不是经常用webservice的菜鸟来说,经常会遇到以下的问题(起码我是遇到了) 在页面上写了js调用代码如下所示: ...
- Mac下输入法总是默认中文,怎么设置成英文的?
最近一同事在DreamWeaver里,写CSS样式的时候,默认总是中文,切到别的窗口,再切回来,就变成中文了,总要按一下切换键,时间长了特别烦人. 在网上找了一些方法,最后找到一个有效的. 总结一下就 ...
- PL/SQL Developer连接Oracle 11g在Win8 64位系统下乱码
PL/SQL Developer在64位系统上连接Oracle,需要安装32位Oracle client客户端,使用后,发现操作数据库出现乱码的情况.经过查找资料,解决此问题,方法如下: 需要在系统的 ...