JS中的空值

更新日期: 2019-10-08阅读: 3k标签: null

尽管从第一次遇到空值引起的bug开始,我就一直要求自己注意空值,但还是经常犯这样的错误,JS中的空值真的需要多加注意。这里说的空值包括undefined和null


为什么JS容易出现空值bug?

首先JS是一个动态类型语言,与之相对的是静态类型语言如Java。在Java中要定义数据模型意味着定义一个类——JavaBean,无论这个数据模型的结构多么简单。在JS中就简单的多:

var auth = {
  visible: true,
  editable: true
}

这种灵活的方式带来了很大的便捷,但这种便捷是有代价的。JS并不能保证所有的auth对象是同样的结构,auth.visible并不一定是布尔型,有可能是undefined或者其它类型的数据。尽管定义一个JavaBean有些麻烦,Java中不会出现这样的情况——你可以确定一个auth对象一定有一个布尔型的visible属性。


空值bug会以哪些形式出现?

有的时候定义数据时会默认{}或者undefined就是{visible: false, enbale: false},或者{name: 'afei'}就是{name: 'afei': phone: ''}。在使用数据时很容易遗漏这种隐藏逻辑,从而引发bug。而且这种空值只在少部分情况下出现,很容易躲过测试。

function fn (obj) {
  console.log(obj[key].id);
}

这里obj或者obj[key]为空都会导致报错。

function fn (authArray) {
  authArray.forEach(function (i, auth) {
    console.log(auth.visible);
  })
}

这种形式就更具迷惑性,你很容易就觉得authArray里面肯定都是auth吧,既然是auth肯定有visible属性吧。然而并没有人能保证这一点,authArray里面可能有别的数据:空值或者没有visible属性的auth对象。

function fn (authIdArray, authMap) {
  authIdArray.forEach(function (i, authId) {
    var auth = authMap[authId];
    console.log(auth.visible);
  })
}

同样,看到authIdArray和authMap,很容易觉得它们一定是一一对应的,应该可以取到一个auth对象。

总而言之,JS并不能保证数据的结构化,而开发过程中很容易默认取到的是结构化数据。


怎么解决

遇到空值bug有两种解决方案。

在取值的地方加判断

function fn (auth) {
  var val = obj[key];
  if (val) {
    console.log(val.id);
  }
}

还有一种写法:

function fn (obj) {
  console.log(obj[key] && obj[key].id);
}

在变量声明和赋值的地方保证数据结构一致

var auth = {
  visible: booleanVal || false
}

authArray.push(authObj || {});

authMap[id] = authObj || {};

如果auth的某个属性还不是基础类型,可能更麻烦一些——不能用{}来代替auth。

第一种方法改动起来更简单,但是第二种方法能保持数据结构一致,有利于代码的长期维护。一种比较中庸的方法是:在私有方法中声明和赋值时保证数据的结构一致,在公共方法中接收的变量则检查数据结构(JS不区分公共和私有方法,一个约定俗成的做法是私有方法加上下划线前缀)。


从TypeScript得到的启示

TypeScript是一种由微软开发的自由和开源的编程语言。它是JavaScript的一个严格超集,并添加了可选的静态类型和基于类的面向对象编程。所谓可选的静态类型可以理解为灵活范式——本来是无范式的。TypeScript可以声明参数或属性的数据类型,在编译时进行类型检查,也可以通过any类型来跳过类型检查。 使用TypeScript后IDE的补全和跳转可以像静态语言一样,对开发者更加友好,数据类型引起的bug也会大大减少。从使用者评价来看,大型项目中使用TypeScript有助于提高开发效率和减少bug。

fx-code工程引入TypeScript的障碍有两点:一是工程中没有实现模块化而是AllInOne模式,不能在一个组件中引入另外一个组件,TypeScript也就没办法发挥作用。二是遗留代码需要编写大量的声明文件,而且需要开发者转换静态类型语言的思维。

在引入之前或者不引入的话,我们也可以通过注释来起到申明数据类型的作用。

/**
* @param fields {Array<Field>}
* @interface
* 	Field {
* 		name: string,
* 		text: string,
* 		enbale: boolean | undefined,
* 		layout: 6 | 12
* 	}
* @return void
*/
function fn (fields, fieldAuth) {
  // ...
}

对于可能为undefined和{}的变量的注释尤其要详细。


链接: https://www.fly63.com/article/detial/5763

Null空对象模式

在这个快速教程中,我们将看一下Null对象模式,这是设计模式的一个特例,一个经常被我们遗忘的特例。我们将描述它的目的以及我们何时应该考虑使用它。像往常一样,我们还将提供一个简单的代码示例。

Js中Undefined和Null

js中一共有5种简单数据类型:Undefined, Null, boolean, Number, String. 还有一种复杂的数据类型:Object,本篇主要介绍Undefined和Null

js中的null和undefined

null和undefined属于js中两种不同的基本数据类型,都可以表示“没有”,含义非常相似。将一个变量赋值为undefined或null,老实说,语法效果几乎没区别。并且在if语句的判断条件中,它们都会自动转为false

解决Js中处理null和undefined的麻烦事

许多 JavaScript 开发人员正在为怎么处理可选值头痛。有什么好办法来最大程度地减少由值(可能为 null、undefined或在运行时未初始化)引起的错误?在某些情况下,一些语言具有内置功能。在某些静态类型的语言中

关于null>=0为true

我们今天讨论的主要内容,并不是这个结果可能看起来多么奇怪. 而是为什么会这样. 之所以特别记一篇随笔在这里,主要是因为,我在得到了 Brendan Eich 的一些确认后.发现答案和我当初的猜测不一样

Js中undefined和null的区别是什么

在JavaScript中值undefined和null都表示”无”,那么它们之间有什么区别?undefined:在 JavaScript 中, undefined 是一个没有设置值的变量。typeof 一个没有值的变量会返回 undefined。null是一个只有一个值的特殊类型。表示一个空对象引用。

JavaScript 中 undefined 与 null 的用法区别

大多数计算机语言,有且仅有一个表示“无”的值,比如:C 语言的 NULL,Java 语言的 null,Python 语言的 None,Ruby 语言的 nil。但是在 JavaScript 中却同时存在 undefined 和 null

关于 JavaScript 中 null 的一切

JavaScript 有两种类型:原始类型(strings, booleans, numbers, symbols)和对象,对象是一个复杂的数据结构。最简单的 JavaScript 对象是普通对象 —— 键和相关值的集合

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!