编写可维护的javascript(八):避免“空比较”
来源:互联网 发布:迷彩服淘宝分类 编辑:程序博客网 时间:2024/05/18 20:36
在Javascript中,常常看到这种代码:变量和null的比较,如下:
var Controller = { process: function(items) { if (items !== null) { // bad items.sort(); item.forEach(function(item) { // 执行代码逻辑 }); } } };
这段代码中,process() 方法显然是希望items是一个数组,如果参数不是一个数组,则停止接下来的操作。
问题在于,仅仅和null比较并不能提供足够的信息来判断变量是否为一个数组。好在可以Javascript提供了多种方法检测变量的真实值。
检测原始值
Javascript的数据类型有:字符串、数字、布尔值、Null、Undefined、对象、Symbol(ES6新增数据类型);
Javascript有6中原始数据类型:字符串、数字、布尔值、Null、Undefined、Symbol。
typeof 运算符会返回一个表示值得类型的字符串(typeof是一个运算符不是函数)
- 对于字符串,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运算符的独特之处是,将其用于一个未声明的变量也不会报错。未定义的变量和值为undefined的变量通过typeof都将返回”undefined”。
当然如果你所期望的值是null,则可以直接和null进行比较。这时应当使用===或者!==来和null进行比较。比如:
// 如果你需要检测null,则使用这种方法 var element = document.getElementById('my-div'); if (element !== null) { element.className = "found"; }
运行typeof null则返回“object”,这是一种低效的判断null的方法。如果你需要检测null,则直接使用恒等运算符(===)或非恒等运算符(!==)。
检测引用值
引用值也称作对象(object)。
在Javascript中除了原始值之外的都是引用值。有这几种内置引用类型:Object、Array、Date和Error等。typeof运算符在判断这些引用类型的时则显得力不从心,因为所有对象都会返回“object”。
console.log(typeof {}); // object console.log(typeof []); // object console.log(typeof new RegExp()); // object console.log(typeof new Date()); // object 注: console.log(typeof new Function()); // function (ECMA-262条款中实现了,称为函数对象)
typeof另外一种不推荐的用法就是当检测null的类型时,typeof运算符用于null时将返回“object”。
console.log(typeof null); // object
这很怪异(null明明是原始类型值),被认为是标准规范的bug,因此在编程时要杜绝使用typeof来检测null的类型。检测某个引用值的最好方法是使用instanceof运算符。如下例子:
// 检测日期 if (value instanceof Date) { console.log(value.getFullYear()); } // 检测正则 if (value instanceof RegExp) { // 代码 } // 检测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运算符也可以检测自定义的类型,如下:
function Person(name) { this.name = name; } var me = new Person("Mangoyi"); console.log(me instanceof Person); // true console.log(me instanceof Object); // true
代码中创建了Person类型,变量me是Person的实例,因此me instanceof Person是true。
当然所有对象都被认为是Object的实例,因此me instanceof Object也是true。
函数和数组这两个类型来说,一般也用不着使用instanceof。
检测函数
从技术上讲,Javascript中的函数都是引用类型,同样存在Function构造函数,每个函数都是其实例。
function myFunc() {} // bad console.log(myFunc instanceof Function); // true
然而这个方法不能跨帧(frame)使用,因为每个帧都有各自的Function构造函数。好在typeof运算符可以用于函数,返回“function”。
function myFunc() {} // good console.log(typeof myFunc === "function"); // true
检测函数最好的方法是使用typeof,因为它可以跨帧使用。
检测数组
在ECMAScript5中将Array.isArray() 正式引入到Javascript。唯一的目的就是准确的检测一个值是否为数组。底层的实现如下:
function isArray(value) { if (typeof Array.isArray === "function") { return Array.isArray(value); } else { return Object.prototype.toString.call(value) === "[object Array]"; } }
调用内置的toString() 方法在所有浏览器中都会返回标准的字符串结果。对于数组来说,返回的字符串是“[object Array]”。
检测属性
判断属性是否存在最好的方法就是使用in运算符。
in运算符仅仅会简单地判断属性是否存在,而不会去读属性的值。
如果实例对象的属性存在、或者继承自对象的原型,in运算符都会返回true。如下:
var object = { count: 0, related: null }; // good if ("count" in object) { // 这里的代码会执行 } // bad(检测假值) if (object["count"]) { // 这里的代码不会执行 } // good if ("related" in object) { // 这里的代码会执行 } // bad(检测是否为null) if (object["related"] !== null) { // 这里的代码不会执行 }
如果你想检查 实例对象 的某个属性是否存在,则使用hasOwnProperty() 方法。
所有继承自Object的JavaScript对象都有这个方法,如果实例中存在这个属性则返回true(如果这个属性只存在原型里而实例中不存在,则返回false)。
if (object.hasOwnProperty("related")) { // 代码 }
文章内容从《编写可维护的Javascript》[美] Nicholas C. Zakas著 一书中总结写出。
- 编写可维护的javascript(八):避免“空比较”
- 编写可维护的javascript:避免空比较
- 编写可维护的javascript(六):避免使用全局变量
- 编写可维护的JavaScript
- 《编写可维护的javascript》
- 编写可维护的javascript
- 编写可维护的javascript(一):基本的格式化
- 编写可维护的javascript读后笔记(一)
- 编写可维护的javascript读后笔记(二)
- 编写可维护的JavaScript学习笔记(一)
- 编写可维护的 JavaScript 笔记 (1-3章)
- 编写可维护的 JavaScript 笔记 (4-5章)
- 编写可维护的 JavaScript 笔记(8-10 章)
- 编写可维护的javascript(二):注释
- 编写可维护的javascript(三):语句和表达式
- 编写可维护的javascript(十):抛出自定义错误
- 如何编写可维护的JavaScript代码?
- 编写可维护的JavaScript读书笔记(1)
- 架设 Amoeba 服务器(来源网络只作为个人笔记)
- java字符转码:三种方法
- 自定义标签&编码实战170723
- 优先队列
- iOS转前端之如何适配不同屏幕尺寸方案
- 编写可维护的javascript(八):避免“空比较”
- 性能分析工具perf的使用
- hdu6034-贪心
- Android零基础入门第16节:Android用户界面开发概述
- 模拟SDUT OJ登陆
- SpringMVC之@ModelAttribute学习
- 微信小程序免费SSL证书https、TLS版本问题的解决方案
- 737
- 闭锁、同步屏障、信号量详解