javascript
处理 JS中 undefined 的7个技巧
今天跟大家分享下處理JS中undefined的7個技巧的知識。
前言
大約8年前,開始學(xué)習(xí)JS時,遇到了一個奇怪的情況,既存在undefined 的值,也存在表示空值的null。它們之間的明顯區(qū)別是什么?它們似乎都定義了空值,而且,比較null == undefined的計算結(jié)果為true。
大多數(shù)現(xiàn)代語言,如Ruby、Python或Java都有一個空值(nil或null),這似乎是一種合理的方式。
對于JavaScript,解釋器在訪問尚未初始化的變量或?qū)ο髮傩詴r返回undefined。例如:
let company; company; // => undefined let person = { name: 'John Smith' }; person.age; // => undefined另一方面,null表示缺少的對象引用,JS本身不會將變量或?qū)ο髮傩栽O(shè)置為null。
一些原生方法,比如String.prototype.match(),可以返回null來表示丟失的對象。看看下面的示例:
let array = null; array; // => null let movie = { name: 'Starship Troopers', musicBy: null }; movie.musicBy; // => null 'abc'.match(/[0-9]/); // => null由于 JS 的寬容特性,開發(fā)人員很容易訪問未初始化的值,我也犯了這樣的錯誤。
通常,這種危險的操作會生成undefined 的相關(guān)錯誤,從而快速地結(jié)束腳本。相關(guān)的常見錯誤消息有:
TypeError: 'undefined' is not a function TypeError: Cannot read property '<prop-name>' of undefined type errorsJS 開發(fā)人員可以理解這個笑話的諷刺:
functionundefined(){ // problem solved }為了降低此類錯誤的風(fēng)險,必須理解生成undefined的情況。更重要的是抑制它的出現(xiàn)并阻止在應(yīng)用程序中傳播,從而提高代碼的持久性。
讓咱們詳細討論undefined 及其對代碼安全性的影響。
1 undefined是什么鬼
JS 有6種基本類型
Boolean: true 或 false
Number: 1, 6.7, 0xFF
String: “Gorilla and banana”
Symbol: Symbol(“name”) (starting ES2015)
Null: null
Undefined: undefined.
和一個單獨的Object 類型:{name: “Dmitri”}, [“apple”, “orange”]。
根據(jù)ECMAScript規(guī)范,從6種原始類型中,undefined是一個特殊的值,它有自己的Undefined類型。
未為變量賦值時默認值為undefined。
該標(biāo)準(zhǔn)明確定義,當(dāng)訪問未初始化的變量、不存在的對象屬性、不存在的數(shù)組元素等時,將接收到一個undefined 的值。例如
let number; number; // => undefined let movie = { name: 'Interstellar' }; movie.year; // => undefined let movies = ['Interstellar', 'Alexander']; movies[3]; // => undefined上述代碼大致流程:
未初始化的變量number
一個不存在的對象屬性movie.year
或者不存在數(shù)組元素movies[3]
都會被定義為undefined。
ECMAScript規(guī)范定義了undefined 值的類型
Undefined type是其唯一值為undefined 值的類型。
在這個意義上,typeof undefined返回“undefined”字符串
typeofundefined==='undefined';// => true當(dāng)然typeof可以很好地驗證變量是否包含undefined的值
let nothing; typeofnothing ==='undefined';// => true2 創(chuàng)建未定義的常見場景
2.1 未初始化變量
尚未賦值(未初始)的聲明變量默認為undefined。
myVariable已聲明,但尚未賦值,默認值為undefined。
解決未初始化變量問題的有效方法是盡可能分配初始值。變量在未初始化狀態(tài)中越少越好。理想情況下,你可以在聲明const myVariable ='Initial value’之后立即指定一個值,但這并不總是可行的。
技巧1:使用 let 和 const 來代替 var
在我看來,ES6 最好的特性之一是使用const和let聲明變量的新方法。const和let具有塊作用域(與舊的函數(shù)作用域var相反),在聲明行之前都存在于暫時性死區(qū)。
當(dāng)變量一次性且永久地接收到一個值時,建議使用const聲明,它創(chuàng)建一個不可變的綁定。
const的一個很好的特性是必須為變量const myVariable ='initial’分配一個初始值。變量未暴露給未初始化狀態(tài),并且訪問undefined是不可能的。
以下示例檢查驗證一個單詞是否是回文的函數(shù):
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'); // => true isPalindrome('hello'); // => falselength 和 half 變量被賦值一次。將它們聲明為const似乎是合理的,因為這些變量不會改變。
如果需要重新綁定變量(即多次賦值),請應(yīng)用let聲明。只要可能,立即為它賦一個初值,例如,let index = 0。
那么使用 var 聲明呢,相對于ES6,建議是完全停止使用它。
var 聲明的變量提會被提升到整個函數(shù)作用域頂部。可以在函數(shù)作用域末尾的某個地方聲明var變量,但是仍然可以在聲明之前訪問它:對應(yīng)變量的值是 undefined。
相反,用let 或者 const 聲明的變量之前不能訪問該變量。之所以會發(fā)生這種情況,是因為變量在聲明之前處于暫時死區(qū)。這很好,因為這樣就很少有機會訪問到 undefined 值。
使用let(而不是var)更新的上述示例會引發(fā)ReferenceError 錯誤,因為無法訪問暫時死區(qū)中的變量。
function bigFunction() {// code...myVariable; // => Throws 'ReferenceError: myVariable is not defined'// code...let myVariable = 'Initial value';// code...myVariable; // => 'Initial value' } bigFunction();技巧2:增加內(nèi)聚性
內(nèi)聚描述模塊的元素(命名空間、類、方法、代碼塊)內(nèi)聚在一起的程度。凝聚力的測量通常被稱為高凝聚力或低內(nèi)聚。
高內(nèi)聚是優(yōu)選的,因為它建議設(shè)計模塊的元素以僅關(guān)注單個任務(wù),它構(gòu)成了一個模塊。
專注且易懂:更容易理解模塊的功能
可維護且更容易重構(gòu):模塊中的更改會影響更少的模塊
可重用:專注于單個任務(wù),使模塊更易于重用
可測試:可以更輕松地測試專注于單個任務(wù)的模塊
高內(nèi)聚和低耦合是一個設(shè)計良好的系統(tǒng)的特征。
代碼塊本身可能被視為一個小模塊,為了盡可能實現(xiàn)高內(nèi)聚,需要使變量盡可能接近使用它們代碼塊位置。
例如,如果一個變量僅存在以形成塊作用域內(nèi),不要將此變量公開給外部塊作用域,因為外部塊不應(yīng)該關(guān)心此變量。
不必要地延長變量生命周期的一個典型例子是函數(shù)中for循環(huán)的使用:
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'; }index,item和length變量在函數(shù)體的開頭聲明,但是,它們僅在最后使用,那么這種方式有什么問題呢?
從頂部的聲明到for語句中變量 index 和 item 都是未初始化的,值為 undefined。它們在整個函數(shù)作用域內(nèi)具有不合理較長的生命周期。
一種更好的方法是將這些變量盡可能地移動到使用它們的位置:
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'; }index和item變量僅存在于for語句的作用域內(nèi),for 之外沒有任何意義。length變量也被聲明為接近其使用它的位置。
為什么修改后的版本優(yōu)于初始版本?主要有幾點:
變量未暴露undefined狀態(tài),因此沒有訪問undefined的風(fēng)險
將變量盡可能地移動到它們的使用位置會增加代碼的可讀性
高內(nèi)聚的代碼塊在必要時更容易重構(gòu)并提取到單獨的函數(shù)中
2.2 訪問不存在的屬性
訪問不存在的對象屬性時,JS 返回undefined。
咱們用一個例子來說明這一點:
let favoriteMovie = {title: 'Blade Runner' }; favoriteMovie.actors; // => undefinedfavoriteMovie是一個具有單個屬性 title 的對象。使用屬性訪問器favoriteMovie.actors訪問不存在的屬性actors將被計算為undefined。
本身訪問不存在的屬性不會引發(fā)錯誤, 但嘗試從不存在的屬性值中獲取數(shù)據(jù)時就會出現(xiàn)問題。常見的的錯誤是 TypeError: Cannot read property of undefined。
稍微修改前面的代碼片段來說明TypeError throw:
let favoriteMovie = {title: 'Blade Runner' }; favoriteMovie.actors[0]; // TypeError: Cannot read property '0' of undefinedfavoriteMovie沒有屬性actors,所以favoriteMovie.actors的值 undefined。因此,使用表達式favoriteMovie.actors[0]訪問undefined值的第一項會引發(fā)TypeError。
JS 允許訪問不存在的屬性,這種允許訪問的特性容易引起混淆:可能設(shè)置了屬性,也可能沒有設(shè)置屬性,繞過這個問題的理想方法是限制對象始終定義它所持有的屬性。
不幸的是,咱們常常無法控制對象。在不同的場景中,這些對象可能具有不同的屬性集,因此,必須手動處理所有這些場景:
接著我們實現(xiàn)一個函數(shù)append(array, toAppend),它的主要功能在數(shù)組的開頭和/或末尾添加新的元素。toAppend參數(shù)接受具有屬性的對象:
first:元素插入數(shù)組的開頭
last:元素在數(shù)組末尾插入。
函數(shù)返回一個新的數(shù)組實例,而不改變原始數(shù)組(即它是一個純函數(shù))。
append()的第一個版本看起來比較簡單,如下所示:
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]由于toAppend對象可以省略first或last屬性,因此必須驗證toAppend中是否存在這些屬性。如果屬性不存在,則屬性訪問器值為undefined。
檢查first或last屬性是否是undefined,在條件為 if(toappendix .first){}和if(toappendix .last){}中進行驗證:
這種方法有一個缺點, undefined,false,null,0,NaN和’'是虛值。
在append() 的當(dāng)前實現(xiàn)中,該函數(shù)不允許插入虛值元素:
append([10], { first: 0, last: false }); // => [10]0和false是虛值的。因為 if(toAppend.first){}和if(toAppend.last){}實際上與falsy進行比較,所以這些元素不會插入到數(shù)組中,該函數(shù)返回初始數(shù)組[10]而不會進行任何修改。
以下技巧解釋了如何正確檢查屬性的存在。
技巧3:檢查屬性是否存在
JS 提供了許多方法來確定對象是否具有特定屬性:
我的建議是使用 in 操作符,它的語法短小精悍。in操作符的存在表明一個明確的意圖,即檢查對象是否具有特定的屬性,而不訪問實際的屬性值。
obj.hasOwnProperty(‘prop’)也是一個很好的解決方案,它比 in 操作符稍長,僅在對象自己的屬性中進行驗證。
涉及與undefined進行比較剩下的兩種方式可能有效,但在我看來,obj.prop!== undefined和typeof obj.prop!=='undefined’看起來冗長而怪異,并暴露出直接處理undefined的可疑路徑。
讓咱們使用in操作符改進append(array, toAppend) 函數(shù):
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]‘first’ in toAppend (和’last’ in toAppend)在對應(yīng)屬性存在時為true,否則為false。in操作符的使用解決了插入虛值元素0和false的問題。現(xiàn)在,在[10]的開頭和結(jié)尾添加這些元素將產(chǎn)生預(yù)期的結(jié)果[0,10,false]。
技巧4:解構(gòu)訪問對象屬性
在訪問對象屬性時,如果屬性不存在,有時需要指示默認值。可以使用in和三元運算符來實現(xiàn)這一點。
當(dāng)要檢查的屬性數(shù)量增加時,三元運算符語法的使用變得令人生畏。對于每個屬性,都必須創(chuàng)建新的代碼行來處理默認值,這就增加了一堵難看的墻,里面都是外觀相似的三元運算符。
為了使用更優(yōu)雅的方法,可以使用 ES6 對象的解構(gòu)。
對象解構(gòu)允許將對象屬性值直接提取到變量中,并在屬性不存在時設(shè)置默認值,避免直接處理undefined的方便語法。
實際上,屬性提取現(xiàn)在看起來簡短而有意義:
const object = { }; const { prop = 'default' } = object; prop; // => 'default'要查看實際操作中的內(nèi)容,讓我們定義一個將字符串包裝在引號中的有用函數(shù)。quote(subject, config)接受第一個參數(shù)作為要包裝的字符串。第二個參數(shù)config是一個具有以下屬性的對象:
char:包裝的字符,例如 '(單引號)或“(雙引號),默認為”。
skipIfQuoted:如果字符串已被引用則跳過引用的布爾值,默認為true。
使用對象析構(gòu)的優(yōu)點,讓咱們實現(xiàn)quote()
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 = ‘", skipifquote = true} = config解構(gòu)賦值在一行中從config對象中提取char和skipifquote屬性。如果config對象中有一些屬性不可用,那么解構(gòu)賦值將設(shè)置默認值:char為’"’,skipifquote為false。
該功能仍有改進的空間。讓我們將解構(gòu)賦值直接移動到參數(shù)部分。并為config參數(shù)設(shè)置一個默認值(空對象{}),以便在默認設(shè)置足夠時跳過第二個參數(shù)。
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"'注意,解構(gòu)賦值替換了函數(shù) config 參數(shù)。我喜歡這樣:quote()縮短了一行。={}在解構(gòu)賦值的右側(cè),確保在完全沒有指定第二個參數(shù)的情況下使用空對象。
對象解構(gòu)是一個強大的功能,可以有效地處理從對象中提取屬性。我喜歡在被訪問屬性不存在時指定要返回的默認值的可能性。因為這樣可以避免undefined以及與處理它相關(guān)的問題。
技巧5:用默認屬性填充對象
如果不需要像解構(gòu)賦值那樣為每個屬性創(chuàng)建變量,那么丟失某些屬性的對象可以用默認值填充。
ES6 Object.assign(target,source1,source2,…)將所有可枚舉的自有屬性的值從一個或多個源對象復(fù)制到目標(biāo)對象中,該函數(shù)返回目標(biāo)對象。
例如,需要訪問unsafeOptions對象的屬性,該對象并不總是包含其完整的屬性集。
為了避免從unsafeOptions訪問不存在的屬性,讓我們做一些調(diào)整:
定義包含默認屬性值的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; // => 18 options.color; // => 'black'unsafeOptions僅包含fontSize屬性。defaults對象定義屬性fontSize和color的默認值。
Object.assign() 將第一個參數(shù)作為目標(biāo)對象{}。目標(biāo)對象從unsafeOptions源對象接收fontSize屬性的值。并且人defaults對象的獲取color屬性值,因為unsafeOptions不包含color屬性。
枚舉源對象的順序很重要:后面的源對象屬性會覆蓋前面的源對象屬性。
現(xiàn)在可以安全地訪問options對象的任何屬性,包括options.color在最初的unsafeOptions中是不可用的。
還有一種簡單的方法就是使用ES6中展開運算符:
const unsafeOptions = {fontSize: 18 }; const defaults = {fontSize: 16,color: 'black' }; const options = {...defaults,...unsafeOptions }; options.fontSize; // => 18 options.color; // => 'black'對象初始值設(shè)定項從defaults和unsafeOptions源對象擴展屬性。指定源對象的順序很重要,后面的源對象屬性會覆蓋前面的源對象。
使用默認屬性值填充不完整的對象是使代碼安全且持久的有效策略。無論哪種情況,對象總是包含完整的屬性集:并且無法生成undefined的屬性。
2.3 函數(shù)參數(shù)
函數(shù)參數(shù)隱式默認為undefined。
通常,用特定數(shù)量的參數(shù)定義的函數(shù)應(yīng)該用相同數(shù)量的參數(shù)調(diào)用。在這種情況下,參數(shù)得到期望的值。
function multiply(a, b) {a; // => 5b; // => 3return a * b; } multiply(5, 3); // => 15調(diào)用multiply(5,3)使參數(shù)a和b接收相應(yīng)的5和3值,返回結(jié)果:5 * 3 = 15。
在調(diào)用時省略參數(shù)會發(fā)生什么?
function multiply(a, b) {a; // => 5b; // => undefinedreturn a * b; } multiply(5); // => NaN函數(shù)multiply(a, b){}由兩個參數(shù)a和b定義。調(diào)用multiply(5)用一個參數(shù)執(zhí)行:結(jié)果一個參數(shù)是5,但是b參數(shù)是undefined。
技巧6:使用默認參數(shù)值
有時函數(shù)不需要調(diào)用的完整參數(shù)集,可以簡單地為沒有值的參數(shù)設(shè)置默認值。
回顧前面的例子,讓我們做一個改進,如果b參數(shù)未定義,則為其分配默認值2:
function multiply(a, b) {if (b === undefined) {b = 2;}a; // => 5b; // => 2return a * b; } multiply(5); // => 10雖然所提供的分配默認值的方法有效,但不建議直接與undefined值進行比較。它很冗長,看起來像一個hack .
這里可以使用 ES6 的默認值:
function multiply(a, b = 2) {a; // => 5b; // => 2return a * b; } multiply(5); // => 10 multiply(5, undefined); // => 102.4 函數(shù)返回值
隱式地,沒有return語句,JS 函數(shù)返回undefined。
在JS中,沒有任何return語句的函數(shù)隱式返回undefined:
function square(x) {const res = x * x; } square(2); // => undefinedsquare() 函數(shù)沒有返回計算結(jié)果,函數(shù)調(diào)用時的結(jié)果undefined。
當(dāng)return語句后面沒有表達式時,默認返回 undefined。
function square(x) {const res = x * x;return; } square(2); // => undefinedreturn; 語句被執(zhí)行,但它不返回任何表達式,調(diào)用結(jié)果也是undefined。
function square(x) {const res = x * x;return res; } square(2); // => 4技巧7:不要相信自動插入分號
JS 中的以下語句列表必須以分號(;)結(jié)尾:
如果使用上述聲明之一,請盡量務(wù)必在結(jié)尾處指明分號:
function getNum() {let num = 1; return num; } getNum(); // => 1let 聲明和return 語句結(jié)束時,強制性寫分號。
當(dāng)你不想寫這些分號時會發(fā)生什么?例如,咱們想要減小源文件的大小。
在這種情況下,ECMAScript 提供自動分號插入(ASI)機制,為你插入缺少的分號。
ASI 的幫助下,可以從上一個示例中刪除分號:
function getNum() {// Notice that semicolons are missinglet num = 1return num } getNum() // => 1上面的代碼是有效的JS代碼,缺少的分號ASI會自動為我們插入。
乍一看,它看起來很 nice。ASI 機制允許你少寫不必要的分號,可以使JS代碼更小,更易于閱讀。
ASI 創(chuàng)建了一個小而煩人的陷阱。當(dāng)換行符位于return和return \n expression之間時,ASI 會在換行符之前自動插入分號(return; \n expression)。
函數(shù)內(nèi)部return; ?即該函數(shù)返回undefined。如果你不詳細了解ASI的機制,則意外返回的undefined會產(chǎn)生意想不到的問題。
來 getPrimeNumbers()調(diào)用返回的值:
function getPrimeNumbers() {return [ 2, 3, 5, 7, 11, 13, 17 ] } getPrimeNumbers() // => undefined在return語句和數(shù)組之間存在一個換行,JS 在return后自動插入分號,解釋代碼如下:
function getPrimeNumbers() {return; [ 2, 3, 5, 7, 11, 13, 17 ]; } getPrimeNumbers(); // => undefinedreturn; 使函數(shù)getPrimeNumbers() 返回undefined而不是期望的數(shù)組。
這個問題通過刪除return和數(shù)組文字之間的換行來解決:
function getPrimeNumbers() {return [ 2, 3, 5, 7, 11, 13, 17 ]; } getPrimeNumbers(); // => [2, 3, 5, 7, 11, 13, 17]我的建議是研究自動分號插入的確切方式,以避免這種情況。
當(dāng)然,永遠不要在return和返回的表達式之間放置換行符。
2.5 void 操作符
void 計算表達式無論計算結(jié)果如何都返回undefined
void操作符的一個用例是將表達式求值限制為undefined,這依賴于求值的一些副作用。
未定義的數(shù)組
訪問越界索引的數(shù)組元素時,會得到undefined 。
colors數(shù)組有3個元素,因此有效索引為0,1和2。
因為索引5和-1沒有數(shù)組元素,所以訪問colors[5]和colors[-1]值為undefined。
JS 中,可能會遇到所謂的稀疏數(shù)組。這些數(shù)組是有間隙的數(shù)組,也就是說,在某些索引中,沒有定義元素。
當(dāng)在稀疏數(shù)組中訪問間隙(也稱為空槽)時,也會得到一個undefined。
下面的示例生成稀疏數(shù)組并嘗試訪問它們的空槽
const sparse1 = new Array(3); sparse1; // => [<empty slot>, <empty slot>, <empty slot>] sparse1[0]; // => undefined sparse1[1]; // => undefined const sparse2 = ['white', ,'blue'] sparse2; // => ['white', <empty slot>, 'blue'] sparse2[1]; // => undefined使用數(shù)組時,為了避免獲取undefined,請確保使用有效的數(shù)組索引并避免創(chuàng)建稀疏數(shù)組。
undefined和null之間的區(qū)別
一個合理的問題出現(xiàn)了:undefined和null之間的主要區(qū)別是什么?這兩個特殊值都表示為空狀態(tài)。
主要區(qū)別在于undefined表示尚未初始化的變量的值,null表示故意不存在對象。
讓咱們通過一些例子來探討它們之間的區(qū)別。
number 定義了但沒有賦值。
let number; number;// => undefinednumber 變量未定義,這清楚地表明未初始化的變量。
當(dāng)訪問不存在的對象屬性時,也會發(fā)生相同的未初始化概念
const obj = {firstName:'Dmitri'}; obj.lastName;// => undefined因為obj中不存在lastName屬性,所以JS正確地將obj.lastName計算為undefined。
在其他情況下,你知道變量期望保存一個對象或一個函數(shù)來返回一個對象。但是由于某些原因,你不能實例化該對象。在這種情況下,null是丟失對象的有意義的指示器。
例如,clone()是一個克隆普通JS對象的函數(shù),函數(shù)將返回一個對象
function clone(obj) {if (typeof obj === 'object' && obj !== null) {return Object.assign({}, obj);}return null; } clone({name: 'John'}); // => {name: 'John'} clone(15); // => null clone(null); // => null但是,可以使用非對象參數(shù)調(diào)用clone(): 15或null(或者通常是一個原始值,null或undefined)。在這種情況下,函數(shù)不能創(chuàng)建克隆,因此返回null—— 一個缺失對象的指示符。
typeof操作符區(qū)分了這兩個值
typeofundefined;// => 'undefined' typeof null;// => 'object'嚴格相等運算符===可以正確區(qū)分undefined和null:
let nothing =undefined; let missingObject =null; nothing === missingObject;// => false3 總結(jié)
undefined的存在是JS的允許性質(zhì)的結(jié)果,它允許使用:
未初始化的變量 不存在的對象屬性或方法 訪問越界索引的數(shù)組元素 不返回任何結(jié)果的函數(shù)的調(diào)用結(jié)果 大多數(shù)情況下直接與undefined進行比較是一種不好的做法。一個有效的策略是減少代碼中undefined關(guān)鍵字的出現(xiàn): 減少未初始化變量的使用 使變量生命周期變短并接近其使用的位置 盡可能為變量分配初始值 多敷衍 const 和 let 使用默認值來表示無關(guān)緊要的函數(shù)參數(shù) 驗證屬性是否存在或使用默認屬性填充不安全對象 避免使用稀疏數(shù)組關(guān)于處理JS中undefined的7個技巧,你學(xué)會了多少?歡迎在留言區(qū)評論!
總結(jié)
以上是生活随笔為你收集整理的处理 JS中 undefined 的7个技巧的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: dnspod动态解析linux,NAS折
- 下一篇: [Pytorch系列-57]:循环神经网