7个处理JavaScript值为undefined的技巧

let company;company; // => undefinedlet person = { name: 'John Smith' };person.age; // => undefined
let array = null;array; // => nulllet movie = { name: 'Starship Troopers', musicBy: null };movie.musicBy; // => null'abc'.match(/[0-9]/); // => null
TypeError:'undefined'不是函数
TypeError:无法读取未定义的属性'
'' 和类似type errors。
function undefined() {// problem solved}
1、 什么是undefined
Boolean: true or false Number: 1, 6.7, 0xFF String: "Gorilla and banana" Symbol: Symbol("name") (starting ES2015) Null: null Undefined: undefined.
未定义的值原始值在变量未被赋值时使用。
let number;number; // => undefinedlet movie = { name: 'Interstellar' };movie.year; // => undefinedlet movies = ['Interstellar', 'Alexander'];movies[3]; // => undefined
未定义类型是唯一值为“未定义”值的类型。
typeof undefined === 'undefined'; // => true
let nothing;typeof nothing === 'undefined'; // => true
2、 创建未定义的常见场景
2.1 未初始化的变量
一个尚未赋值的声明变量( uninitialized )默认为undefined。
let myvariable;myvariable; // => undefined
function isPalindrome(word) {const length = word.length;const half = Math.floor(length / 2);for (let index = 0; index `< half; index++) {if (word[index] !== word[length - index - 1]) {return false;}}return true;}isPalindrome('madam'); // =>` trueisPalindrome('hello'); // => false

function bigFunction() {// code...myvariable; // => undefined// code...var myVariable = 'Initial value';// code...myVariable; // => 'Initial value'}bigFunction();
function bigFunction() {// code...myVariable; // => Throws 'ReferenceError: myVariable is not defined'// code...let myVariable = 'Initial value';// code...myVariable; // => 'Initial value'}bigFunction();
Focused and understandable: easier to understand what the module does
功能单一且容易理解
Maintainable and easier to refactor: the change in the module affects fewer modules
易于维护和复用
Reusable: being focusing on a single task, it makes the module easier to reuse
重复利用
Testable: you would easier test a module that's focused on a single task
易于测试

function someFunc(array) {var index, item, length = array.length;// some code...// some code...for (index = 0; index < length; index++) {item = array[index];// some code...}return 'some result';}
function someFunc(array) {// some code...// some code...const length = array.length;for (let index = 0; index `< length; index++) {const item = array[index];// some}return 'some result';}
变量不会暴露于未初始化的状态,因此您没有访问未定义的风险
尽可能将变量移动到它们的使用地点增加了代码的可读性
高度连贯的代码块在需要时更容易重构并提取为分离的函数
2.2 访问不存在的属性
When accessing a **non-existing object property**, JavaScript returnsundefined`. 当访问不再的属性时,会返回undefined
let favoriteMovie = {title: 'Blade Runner'};favoriteMovie.actors; // => undefined
let favoriteMovie = {title: 'Blade Runner'};favoriteMovie.actors[0];// TypeError: Cannot read property '0' of undefined
first: element inserted at the beginning of array
last: element inserted at the end of array.
function append(array, toAppend) {const arrayCopy = array.slice();if (toAppend.first) {arrayCopy.unshift(toAppend.first);}if (toAppend.last) {arrayCopy.push(toAppend.last);}return arrayCopy;}append([2, 3, 4], { first: 1, last: 5 }); // => [1, 2, 3, 4, 5]append(['Hello'], { last: 'World' }); // => ['Hello', 'World']append([8, 16], { first: 4 }); // => [4, 8, 16]
append([10], { first: 0, last: false }); // => [10]
typeof obj.prop!=='undefined':验证属性值的类型 *obj.hasOwnProperty('prop'):验证对象是否拥有自己的属性
obj`中的'prop':验证对象是否有自己的或继承的属性
function append(array, toAppend) {const arrayCopy = array.slice();if ('first' in toAppend) {arrayCopy.unshift(toAppend.first);}if ('last' in toAppend) {arrayCopy.push(toAppend.last);}return arrayCopy;}append([2, 3, 4], { first: 1, last: 5 }); // => [1, 2, 3, 4, 5]append([10], { first: 0, last: false }); // => [0, 10, false]
const object = { };const prop = 'prop' in object ? object.prop : 'default';prop; // => 'default'
const object = { };const { prop = 'default' } = object;prop; // => 'default'
function quote(str, config) {const { char = '"', skipIfQuoted = true } = config;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('"Welcome"', { skipIfQuoted: true }); // => '"Welcome"'```const {char =''',skipIfQuoted = true} = config`解构赋值在一行中从`config`对象中提取属性`char`和`skipIfQuoted`如果某些属性在`config`对象中不可用, 解构赋值将默认值设置为:''''''为'char','false'为'skipIfQuoted`。幸运的是,该功能还有改进的空间。让我们将解构赋值移到参数部分。并为`config`参数设置一个默认值(一个空对象`{}`),以在默认设置足够时跳过第二个参数。[Try in repl.it](https://repl.it/HK1b/0)```javascriptfunction 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"'
定义一个保存默认属性值的对象defaults
调用Object.assign({},defaults,unsafeOptions)来构建一个新的对象options。新对象接收来自unsafeOptions的所有属性,但缺少的属性来自defaults。
const unsafeOptions = {fontSize: 18};const defaults = {fontSize: 16,color: 'black'};const options = Object.assign({}, defaults, unsafeOptions);options.fontSize; // => 18options.color; // => 'black'
const unsafeOptions = {fontSize: 18};const defaults = {fontSize: 16,color: 'black'};const options = {...defaults,...unsafeOptions};options.fontSize; // => 18options.color; // => 'black'
2.3 函数的参数
函数参数默认默认为undefined。
function multiply(a, b) {a; // => 5b; // => 3return a * b;}multiply(5, 3); // => 15
function multiply(a, b) {a; // => 5b; // => undefinedreturn a * b;}multiply(5); // => NaN
function multiply(a, b) {if (b === undefined) {b = 2;}a; // => 5b; // => 2return a * b;}multiply(5); // => 10
function multiply(a, b = 2) {a; // => 5b; // => 2return a * b;}multiply(5); // => 10multiply(5, undefined); // => 10
2.4 函数返回值
隐式地,没有return语句,JavaScript函数返回undefined。
function square(x) {const res = x * x;}square(2); // => undefined
function square(x) {const res = x * x;return;}square(2); // => undefined
function square(x) {const res = x * x;return res;}square(2); // => 4
空的陈述
let,const,var,import,export声明
表达式语句
调试器语句
继续语句,break语句
抛出声明
return语句
function getNum() {// Notice the semicolons at the endlet num = 1;return num;}getNum(); // => 1
function getNum() {// Notice that semicolons are missinglet num = 1return num}getNum() // => 1
function getPrimeNumbers() {return[ 2, 3, 5, 7, 11, 13, 17 ]}getPrimeNumbers() // => undefined
function getPrimeNumbers() {return;[ 2, 3, 5, 7, 11, 13, 17 ];}getPrimeNumbers(); // => undefined
function getPrimeNumbers() {return [2, 3, 5, 7, 11, 13, 17];}getPrimeNumbers(); // => [2, 3, 5, 7, 11, 13, 17]
2.5 void 运算
void 1; // => undefinedvoid (false); // => undefinedvoid {name: 'John Smith'}; // => undefinedvoid Math.min(1, 3); // => undefined
3、数组中的undefined
const colors = ['blue', 'white', 'red'];colors[5]; // => undefinedcolors[-1]; // => undefined
const sparse1 = new Array(3);sparse1; // => [``, ` `, ` `] sparse1[0]; // => undefinedsparse1[1]; // => undefinedconst sparse2 = ['white', ,'blue']sparse2; // => ['white', ``, 'blue'] sparse2[1]; // => undefined
4、undefined and null 之间的不同
let number;number; // => undefined
const obj = { firstName: 'Dmitri' };obj.lastName; // => undefined
function clone(obj) {if (typeof obj === 'object' && obj !== null) {return Object.assign({}, obj);}return null;}clone({name: 'John'}); // => {name: 'John'}clone(15); // => nullclone(null); // => null
typeof undefined; // => 'undefined'typeof null; // => 'object'
let nothing = undefined;let missingObject = null;nothing === missingObject; // => false
5、总结
uninitialized variables 未初始化的对象 non-existing object properties or methods 对象没有的方法或属性 out of bounds indexes to access array elements 数组的超出长度下标的元素 the invocation result of a function that returns nothing 当方法调用返回空时
减少未初始化变量的使用
使变量生命周期变短并接近其使用的来源
尽可能为变量分配一个初始值
支持const,否则使用let
使用默认值作为无意义的函数参数
验证属性的存在或用缺省属性填充不安全的对象
避免使用稀疏数组

