typeof undefined === "undefined"; // => true

let nothing; typeof nothing === "undefined"; // => true

 

检查属性是否存在:

JS 提供了许多方法来确定对象是否具有特定属性:

1.obj.prop != undefined 直接和undefined比较

2.typeof obj.prop != 'undefined' 验证属性值类型

3.obj.hasOwnProperty('prop'):验证对象是否具有自己的属性

4.'prop' in obj 验证对象是否具有自己的属性或继承属性

解构访问对象属性:

const object = { }; const { prop = 'default' } = object;

prop; // => 'default'

function quote(str, { char = '"', skipIfQuoted = true } = {}) {
  const length = str.length;
  if (skipIfQuoted
      && str[0] === char
      && str[length - 1] === char) {
    return str;
  }
  return char + str + char;
}
quote('Hello World', { char: '*' }); // => '*Hello World*'
quote('Sunny day');                  // => '"Sunny day"'

={}在解构赋值的右侧,确保在完全没有指定第二个参数的情况下使用空对象。

用默认属性填充对象

ES6 Object.assign(target,source1,source2,...)将所有可枚举的自有属性的值从一个或多个源对象复制到目标对象中,该函数返回目标对象。

枚举源对象的顺序很重要:后面的源对象属性会覆盖前面的源对象属性。const unsafeOptions = {
  fontSize: 18
};
const defaults = {
  fontSize: 16,
  color: 'black'
};
const options = Object.assign({}, defaults, unsafeOptions);
options.fontSize; // => 18
options.color;    // => 'black'
const unsafeOptions = {
  fontSize: 18
};
const defaults = {
  fontSize: 16,
  color: 'black'
};
const options = {
  ...defaults,
  ...unsafeOptions
};
options.fontSize; // => 18
options.color;    // => 'black'

使用默认参数值

function multiply(a, b) {
  if (b === undefined) {
    b = 2;
  }
  a; // => 5
  b; // => 2
  return a * b;
}
multiply(5); // => 10
虽然所提供的分配默认值的方法有效,但不建议直接与undefined值进行比较。它很冗长,看起来像一个hack .

这里可以使用 ES6 的默认值:

function multiply(a, b = 2) {
  a; // => 5
  b; // => 2
  return a * b;
}
multiply(5);            // => 10
multiply(5, undefined); // => 10 

 函数返回值

function square(x) {
  const res = x * x;
}
square(2); // => undefined  
square() 函数没有返回计算结果,函数调用时的结果undefined。

当return语句后面没有表达式时,默认返回 undefined。

function square(x) {
  const res = x * x;
  return;
}
square(2); // => undefined
return; 语句被执行,但它不返回任何表达式,调用结果也是undefined。

function square(x) {
  const res = x * x;
  return res;
}
square(2); // => 4

不要相信自动插入分号

当换行符位于returnreturn \n expression之间时,ASI 会在换行符之前自动插入分号(return; \n expression)。

function getPrimeNumbers() {
  return 
    [ 2, 3, 5, 7, 11, 13, 17 ]
}
getPrimeNumbers() // => undefined
在return语句和数组之间存在一个换行,JS 在return后自动插入分号,解释代码如下:

function getPrimeNumbers() {
  return; 
  [ 2, 3, 5, 7, 11, 13, 17 ];
}
getPrimeNumbers(); // => undefined
return; 使函数getPrimeNumbers() 返回undefined而不是期望的数组。

这个问题通过删除return和数组文字之间的换行来解决:

function getPrimeNumbers() {
  return [ 
    2, 3, 5, 7, 11, 13, 17 
  ];
}
getPrimeNumbers(); // => [2, 3, 5, 7, 11, 13, 17]

void 操作符

void <expression>计算表达式无论计算结果如何都返回undefined 。

void 1;                    // => undefined
void (false);              // => undefined
void {name: 'John Smith'}; // => undefined
void Math.min(1, 3);       // => undefined

总结

undefined的存在是JS的允许性质的结果,它允许使用:

  • 未初始化的变量
  • 不存在的对象属性或方法
  • 访问越界索引的数组元素
  • 不返回任何结果的函数的调用结果

大多数情况下直接与undefined进行比较是一种不好的做法。一个有效的策略是减少代码中undefined关键字的出现:

  • 减少未初始化变量的使用
  • 使变量生命周期变短并接近其使用的位置
  • 尽可能为变量分配初始值
  • 多敷衍 const 和 let
  • 使用默认值来表示无关紧要的函数参数
  • 验证属性是否存在或使用默认属性填充不安全对象
  • 避免使用稀疏数组