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'不是函數(shù)
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、?創(chuàng)建未定義的常見場景
2.1 未初始化的變量
一個尚未賦值的聲明變量(?uninitialized?)默認(rèn)為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
易于維護(hù)和復(fù)用
Reusable: being focusing on a single task, it makes the module easier to reuse
重復(fù)利用
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';}
變量不會暴露于未初始化的狀態(tài),因此您沒有訪問未定義的風(fēng)險
盡可能將變量移動到它們的使用地點增加了代碼的可讀性
高度連貫的代碼塊在需要時更容易重構(gòu)并提取為分離的函數(shù)
2.2 訪問不存在的屬性
When accessing a **non-existing object property**,?JavaScript?returnsundefined`. 當(dāng)訪問不再的屬性時,會返回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`解構(gòu)賦值在一行中從`config`對象中提取屬性`char`和`skipIfQuoted`如果某些屬性在`config`對象中不可用, 解構(gòu)賦值將默認(rèn)值設(shè)置為:''''''為'char','false'為'skipIfQuoted`。幸運(yùn)的是,該功能還有改進(jìn)的空間。讓我們將解構(gòu)賦值移到參數(shù)部分。并為`config`參數(shù)設(shè)置一個默認(rèn)值(一個空對象`{}`),以在默認(rèn)設(shè)置足夠時跳過第二個參數(shù)。[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"'
定義一個保存默認(rèn)屬性值的對象defaults
調(diào)用Object.assign({},defaults,unsafeOptions)來構(gòu)建一個新的對象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 函數(shù)的參數(shù)
函數(shù)參數(shù)默認(rèn)默認(rèn)為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 函數(shù)返回值
隱式地,沒有return語句,JavaScript函數(shù)返回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聲明
表達(dá)式語句
調(diào)試器語句
繼續(xù)語句,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?運(yùn)算
void 1; // => undefinedvoid (false); // => undefinedvoid {name: 'John Smith'}; // => undefinedvoid?Math.min(1,?3);???????//?=>?undefined
3、數(shù)組中的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、總結(jié)
uninitialized variables 未初始化的對象 non-existing object properties or methods 對象沒有的方法或?qū)傩?/span> out of bounds indexes to access array elements 數(shù)組的超出長度下標(biāo)的元素 the invocation result of a function that returns nothing 當(dāng)方法調(diào)用返回空時
減少未初始化變量的使用
使變量生命周期變短并接近其使用的來源
盡可能為變量分配一個初始值
支持const,否則使用let
使用默認(rèn)值作為無意義的函數(shù)參數(shù)
驗證屬性的存在或用缺省屬性填充不安全的對象
避免使用稀疏數(shù)組

