色综合图-色综合图片-色综合图片二区150p-色综合图区-玖玖国产精品视频-玖玖香蕉视频

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

處理JavaScript值為undefined的7個(gè)小技巧

瀏覽:71日期:2023-06-18 18:20:19

前言

我剛剛開(kāi)始學(xué)習(xí)JavaScript時(shí),大約是八年前,當(dāng)時(shí)我對(duì)于undefined 和 null 比較困惑 ,因?yàn)樗麄兌急硎究罩怠?/p>

處理JavaScript值為undefined的7個(gè)小技巧

他們有什么明確的區(qū)別嗎?他們似乎都可以定義一個(gè)空值,而且 當(dāng)你進(jìn)行 在做null ===undefined 的比較時(shí),結(jié)果是true。

現(xiàn)在的大多數(shù)語(yǔ)言,像Ruby, Python or Java,他們有一個(gè)單獨(dú)的空值(nil 或 null),這似乎才是一個(gè)合理的方式。

而在JavaScript里,當(dāng)你要獲取一個(gè)變量或?qū)ο?未初始化)的值時(shí),js引擎會(huì)返回 undefined。

let company; company; // => undefined let person = { name: ’John Smith’ }; person.age; // => undefined

另一方面,對(duì)象引用錯(cuò)誤會(huì)返回null。JavaScript本身并不會(huì)給將變量或者對(duì)象屬性的值設(shè)為 null。

一些js原生的方法會(huì)返回null,比如string.prototypt.match() 參數(shù)不是對(duì)象時(shí),會(huì)返回null,來(lái)表示對(duì)象缺失。

let array = null; array; // => null let movie = { name: ’Starship Troopers’, musicBy: null }; movie.musicBy; // => null ’abc’.match(/[0-9]/); // => null

由于JavaScript的寬容特性,開(kāi)發(fā)人員有訪問(wèn)未初始化值的誘惑。我也犯了這種不好的做法。

通常這種冒險(xiǎn)行為會(huì)產(chǎn)生“未定義”的相關(guān)錯(cuò)誤,從而快速結(jié)束腳本。相關(guān)的常見(jiàn)錯(cuò)誤消息是:

TypeError:’undefined’不是函數(shù) TypeError:無(wú)法讀取未定義的屬性’ ’’ 和類似type errors。

JavaScript開(kāi)發(fā)能夠理解這個(gè)笑話:

function undefined() { // problem solved }

為了減少這種錯(cuò)誤的風(fēng)險(xiǎn),您必須了解產(chǎn)生“undefined”時(shí)的情況。

更重要的是抑制其外觀并在應(yīng)用程序中傳播,從而提高代碼的耐用性。

我們來(lái)詳細(xì)探討undefined及其對(duì)代碼安全的影響。

1、 什么是undefined

JavaScript 的 6 基本類型:

Boolean: true or false Number: 1, 6.7, 0xFF String: 'Gorilla and banana' Symbol: Symbol('name') (starting ES2015) Null: null Undefined: undefined.

And a separated object type: {name: 'Dmitri'}, ['apple', 'orange'].

從6個(gè)基本類型undefined是一個(gè)特殊的值,它的類型為Undefined。根據(jù)[ECMAScript規(guī)范](https://www.ecma-international.org/ecma-262/7.0/#sec-undefined-value):

未定義的值原始值在變量未被賦值時(shí)使用。

該標(biāo)準(zhǔn)明確規(guī)定,在訪問(wèn)未初始化的變量,不存在的對(duì)象屬性,不存在的數(shù)組元素等時(shí),您將收到未定義的值。

例如:Try in repl.it

let number; number; // => undefined let movie = { name: ’Interstellar’ }; movie.year; // => undefined let movies = [’Interstellar’, ’Alexander’]; movies[3]; // => undefined

ECMAScript規(guī)范定義了“未定義”值的類型:

未定義類型是唯一值為“未定義”值的類型。

typeof undefined === ’undefined’; // => true

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

2、 創(chuàng)建未定義的常見(jiàn)場(chǎng)景

2.1 未初始化的變量

一個(gè)尚未賦值的聲明變量( uninitialized )默認(rèn)為undefined。

Plain and simple:

let myvariable; myvariable; // => undefined

解決未初始化變量問(wèn)題的一種有效方法是盡可能分配一個(gè)初始值_。

變量在未初始化狀態(tài)下存在的越少越好。理想情況下,您可以在聲明值const myvariable =’初始值’后立即分配一個(gè)值,但這并非總是可行。

Tip 1: 贊成const,否則使用let,但是告別var

在我看來(lái),ECMAScript 2015的優(yōu)秀功能之一是使用const和let聲明變量的新方法。這是一個(gè)很大的進(jìn)步,這些聲明是塊范圍的(與舊函數(shù)作用域var相反)并存在于[暫時(shí)死區(qū)](https://rainsoft.io/variables-lifecycle-and-why-let- 沒(méi)有被吊起/#5letvariableslifecycle)直到宣告行。

當(dāng)變量只接收一個(gè)值時(shí),我建議使用const聲明。

它創(chuàng)建一個(gè)[不可變綁定](https://mathiasbynens.be/notes/es6-const)。

const的一個(gè)很好的特性是 - 你必須給初始值賦予變量const myvariable =’initial’。變量不會(huì)暴露于未初始化的狀態(tài),并且訪問(wèn)undefined根本不可能。

讓我們檢查一下驗(yàn)證單詞是否是回文的函數(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’); // => false 處理JavaScript值為undefined的7個(gè)小技巧

var聲明的問(wèn)題是整個(gè)函數(shù)范圍內(nèi)的[變量提升](https://rainsoft.io/javascript-hoisting-in-details/#hoistingandvar)。

你可以在函數(shù)范圍的末尾聲明一個(gè)var變量,但是它仍然可以在聲明之前被訪問(wèn):并且你會(huì)得到一個(gè)undefined。

function bigFunction() { // code... myvariable; // => undefined // code... var myVariable = ’Initial value’; // code... myVariable; // => ’Initial value’ } bigFunction();

相反,在聲明行之前不能訪問(wèn)let(包括const)變量。發(fā)生這種情況是因?yàn)樵撟兞吭诼暶髦疤幱赱暫時(shí)死區(qū)](https://rainsoft.io/variables-lifecycle-and-why-let-is-not-hoisted/#5letvariableslifecycle)中。

這很好,因?yàn)槟阍L問(wèn)undefined的機(jī)會(huì)較少。

上面的例子用let改寫(xiě)后,會(huì)出錯(cuò)。

function bigFunction() { // code... myVariable; // => Throws ’ReferenceError: myVariable is not defined’ // code... let myVariable = ’Initial value’; // code... myVariable; // => ’Initial value’ } bigFunction();

Tip 2: 增強(qiáng)內(nèi)聚性

[Cohesion](https://en.wikipedia.org/wiki/Cohesion_(computer_science))描述了模塊(命名空間,類,方法,代碼塊)的元素所屬的程度。 內(nèi)聚的測(cè)量通常被描述為高內(nèi)聚或低內(nèi)聚_。

高內(nèi)聚是最好的,因?yàn)樗ㄗh設(shè)計(jì)模塊的元素只專注于單個(gè)任務(wù)。它使模塊:

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 易于測(cè)試處理JavaScript值為undefined的7個(gè)小技巧

高內(nèi)聚力伴隨[松耦合](https://en.wikipedia.org/wiki/Loose_coupling)是設(shè)計(jì)良好的系統(tǒng)的特點(diǎn)。

一個(gè)代碼塊本身可能被認(rèn)為是一個(gè)小模塊。為了從高內(nèi)聚的好處中受益,您需要盡可能使變量盡可能靠近使用它們的代碼塊。

例如,如果一個(gè)變量完全存在于形成塊范圍的邏輯,則聲明并允許該變量?jī)H存在于該塊內(nèi)(使用const或let聲明)。不要將這個(gè)變量暴露給外部塊作用域,因?yàn)橥獠繅K不應(yīng)該關(guān)心這個(gè)變量。

不必要的擴(kuò)展變量生命周期的一個(gè)典型例子是在函數(shù)內(nèi)使用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ù)體的開(kāi)頭聲明。然而,它們只用于接近尾聲。那么這種方法有什么問(wèn)題?

在頂部的聲明和for語(yǔ)句中的用法之間,變量index,item都是未初始化的并且暴露給undefined。它們?cè)谡麄€(gè)功能范圍內(nèi)的生命周期不合理。

更好的方法是將這些變量盡可能靠近他們的使用地點(diǎn):

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’; }

為什么修改后的版本比最初版本更好?讓我們來(lái)看看:

變量不會(huì)暴露于未初始化的狀態(tài),因此您沒(méi)有訪問(wèn)未定義的風(fēng)險(xiǎn) 盡可能將變量移動(dòng)到它們的使用地點(diǎn)增加了代碼的可讀性 高度連貫的代碼塊在需要時(shí)更容易重構(gòu)并提取為分離的函數(shù)

2.2 訪問(wèn)不存在的屬性

When accessing a **non-existing object property**, JavaScript returnsundefined`. 當(dāng)訪問(wèn)不再的屬性時(shí),會(huì)返回undefined

看例子:

let favoriteMovie = { title: ’Blade Runner’ }; favoriteMovie.actors; // => undefined

本身訪問(wèn)不存在的屬性不會(huì)引發(fā)錯(cuò)誤。嘗試從不存在的屬性值獲取數(shù)據(jù)時(shí)出現(xiàn)真正的問(wèn)題。這是最常見(jiàn)的undefined相關(guān)陷阱,反映在眾所周知的錯(cuò)誤消息’TypeError:Can not read propertyof undefined`中。

讓我們稍微修改前面的代碼片段來(lái)說(shuō)明一個(gè)“TypeError”拋出:

let favoriteMovie = { title: ’Blade Runner’ }; favoriteMovie.actors[0]; // TypeError: Cannot read property ’0’ of undefined

允許訪問(wèn)不存在的屬性的JavaScript的寬容性質(zhì)是混淆的來(lái)源:該屬性可能被設(shè)置,或者可能不是。繞過(guò)這個(gè)問(wèn)題的理想方法是限制對(duì)象始終定義它所擁有的屬性。

不幸的是,您經(jīng)常無(wú)法控制您使用的對(duì)象。這些對(duì)象在不同情況下可能具有不同的屬性集。所以你必須手動(dòng)處理所有這些場(chǎng)景。

讓我們實(shí)現(xiàn)一個(gè)函數(shù)append(array,toAppend),它在數(shù)組的開(kāi)始和/或結(jié)尾添加新的元素。toAppend參數(shù)接受一個(gè)具有屬性的對(duì)象:

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]

下面的提示解釋了如何正確檢查屬性是否存在。

Tip 3: 檢查屬性是否存在

幸運(yùn)的是,JavaScript提供了很多方法來(lái)確定對(duì)象是否具有特定屬性:

*obj.prop!== undefined:直接與undefined進(jìn)行比較

typeof obj.prop!==’undefined’:驗(yàn)證屬性值的類型 *obj.hasOwnProperty(’prop’):驗(yàn)證對(duì)象是否擁有自己的屬性 obj`中的’prop’:驗(yàn)證對(duì)象是否有自己的或繼承的屬性

我的建議是使用in運(yùn)算符。它有一個(gè)簡(jiǎn)短而甜美的語(yǔ)法。in操作符存在意味著明確的目的是檢查對(duì)象是否具有特定的屬性,而不訪問(wèn)實(shí)際的屬性值。

![不要寫(xiě)var,寫(xiě)const并在JavaScript中放置](https://p0.ssl.qhimg.com/t010effea86a232d8a4.png)

obj.hasOwnProperty(’prop’)也是一個(gè)不錯(cuò)的解決方案。它比in運(yùn)算符略長(zhǎng),并且只在對(duì)象自己的屬性中進(jìn)行驗(yàn)證。

涉及與’undefined’比較的兩種方式可能會(huì)起作用......但在我看來(lái)obj.prop!== undefined和typeof obj.prop!==’undefined`看起來(lái)冗長(zhǎng)而怪異,并且暴露直接處理undefined的懷疑路徑。

讓我們使用in運(yùn)算符來(lái)改進(jìn)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]

Tip 4: 用對(duì)象結(jié)構(gòu)的方式訪問(wèn)對(duì)象的屬性

訪問(wèn)對(duì)象屬性時(shí),如果該屬性不存在,有時(shí)需要指示默認(rèn)值。

你可以使用in伴隨著三元運(yùn)算符來(lái)實(shí)現(xiàn):

const object = { }; const prop = ’prop’ in object ? object.prop : ’default’; prop; // => ’default’

當(dāng)要檢查的屬性數(shù)量增加時(shí),三元運(yùn)算符語(yǔ)法的使用會(huì)變得艱巨。對(duì)于每個(gè)屬性,你必須創(chuàng)建一個(gè)新的代碼行來(lái)處理默認(rèn)值,增加類似外觀的三元運(yùn)算符的丑陋墻。

為了使用更優(yōu)雅的方法,讓我們熟悉稱為object destructuring的一個(gè)偉大的ES2015功能。[對(duì)象解構(gòu)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment#Object_destructuring)允許直接將對(duì)象屬性值直接提取到變量中,并設(shè)置默認(rèn)值if 該屬性不存在。

避免直接處理undefined的簡(jiǎn)便語(yǔ)法。

事實(shí)上,現(xiàn)在的屬性解析看起來(lái)簡(jiǎn)短且明了:

const object = { }; const { prop = ’default’ } = object; prop; // => ’default’

為了看到實(shí)際情況,讓我們定義一個(gè)有用的函數(shù),將字符串包裝在引號(hào)中。quote(subject,config)接受第一個(gè)參數(shù)作為要包裝的字符串。第二個(gè)參數(shù)config是一個(gè)具有以下屬性的對(duì)象:

char:引號(hào)字符,例如 (單引號(hào))或(雙引號(hào)),默認(rèn)為`。 skipIfQuoted:如果字符串已被引用,則跳過(guò)引用的布爾值。默認(rèn)為true。

應(yīng)用對(duì)象解構(gòu)的好處,讓我們實(shí)現(xiàn)反引號(hào)的使用:

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`對(duì)象中提取屬性`char`和`skipIfQuoted`如果某些屬性在`config`對(duì)象中不可用, 解構(gòu)賦值將默認(rèn)值設(shè)置為:’’’’’’為’char’,’false’為’skipIfQuoted`。 幸運(yùn)的是,該功能還有改進(jìn)的空間。 讓我們將解構(gòu)賦值移到參數(shù)部分。并為`config`參數(shù)設(shè)置一個(gè)默認(rèn)值(一個(gè)空對(duì)象`{}`),以在默認(rèn)設(shè)置足夠時(shí)跳過(guò)第二個(gè)參數(shù)。 [Try in repl.it](https://repl.it/HK1b/0) ```javascript 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'’

請(qǐng)注意,解構(gòu)賦值將替換函數(shù)簽名中的“config”參數(shù)。我喜歡這樣:quote()變成一行更短。在解構(gòu)賦值右側(cè)的= {}確保在第二個(gè)參數(shù)沒(méi)有在quote(’Sunny day’)`中被指定時(shí)使用空對(duì)象。

對(duì)象解構(gòu)是一個(gè)強(qiáng)大的功能,可以有效地處理從對(duì)象中提取屬性。我喜歡在訪問(wèn)的屬性不存在時(shí)指定要返回的默認(rèn)值的可能性。因此,避免了“未定義”以及與處理它有關(guān)的問(wèn)題。

Tip 5: 用默認(rèn)屬性填充對(duì)象

如果不需要像解構(gòu)分配那樣為每個(gè)屬性創(chuàng)建變量,則缺少某些屬性的對(duì)象可以用缺省值填充。

ES2015Object.assign(target,source1,source2,...)將所有可枚舉屬性的值從一個(gè)或多個(gè)源對(duì)象復(fù)制到目標(biāo)對(duì)象中。該函數(shù)返回目標(biāo)對(duì)象。

例如,您需要訪問(wèn)unsafeOptions對(duì)象的屬性,該屬性并不總是包含其全部屬性。

為了在unsafeOptions中訪問(wèn)一個(gè)不存在的屬性時(shí)避免undefined,讓我們做一些調(diào)整:

定義一個(gè)保存默認(rèn)屬性值的對(duì)象defaults 調(diào)用Object.assign({},defaults,unsafeOptions)來(lái)構(gòu)建一個(gè)新的對(duì)象options。新對(duì)象接收來(lái)自u(píng)nsafeOptions的所有屬性,但缺少的屬性來(lái)自defaults。

const unsafeOptions = { fontSize: 18 }; const defaults = { fontSize: 16, color: ’black’ }; const options = Object.assign({}, defaults, unsafeOptions); options.fontSize; // => 18 options.color; // => ’black’

Object.assign()將第一個(gè)參數(shù)作為目標(biāo)對(duì)象{}。目標(biāo)對(duì)象從unsafeOptions源對(duì)象接收f(shuō)ontSize屬性的值。并且來(lái)自defaults源對(duì)象的color屬性的值,因?yàn)閡nsafeOptions不包含color。枚舉源對(duì)象的順序很重要:稍后的源對(duì)象屬性將覆蓋先前的對(duì)象屬性。

您現(xiàn)在可以安全地訪問(wèn)options對(duì)象的任何屬性,包括最初在unsafeOptions中不可用的options.color。

幸運(yùn)的是,使用默認(rèn)屬性填充對(duì)象的方式更簡(jiǎn)單輕松。我建議使用一個(gè)新的JavaScript特性(現(xiàn)在在[stage 3](https://tc39.github.io/process-document/)),它允許[在對(duì)象初始化器中傳播屬性](https://github.com/ TC39/提議對(duì)象,其余的擴(kuò)展)。

代替Object.assign()調(diào)用,使用對(duì)象擴(kuò)展語(yǔ)法將來(lái)自源對(duì)象的所有屬性和可枚舉屬性復(fù)制到目標(biāo)對(duì)象中:

const unsafeOptions = { fontSize: 18 }; const defaults = { fontSize: 16, color: ’black’ }; const options = { ...defaults, ...unsafeOptions }; options.fontSize; // => 18 options.color; // => ’black’

對(duì)象初始值設(shè)定項(xiàng)從defaults和unsafeOptions源對(duì)象傳播屬性。指定源對(duì)象的順序很重要:稍后的源對(duì)象屬性會(huì)覆蓋先前的對(duì)象屬性。

使用默認(rèn)屬性值填充不完整的對(duì)象是使代碼安全和穩(wěn)定的有效策略。不管情況如何,對(duì)象總是包含全部屬性:’undefined’不能生成。

2.3 函數(shù)的參數(shù)

函數(shù)參數(shù)默認(rèn)默認(rèn)為undefined。

通常,應(yīng)使用相同數(shù)量的參數(shù)調(diào)用使用特定數(shù)量的參數(shù)定義的函數(shù)。在這種情況下,這些參數(shù)將獲得您期望的值:

function multiply(a, b) { a; // => 5 b; // => 3 return a * b; } multiply(5, 3); // => 15

當(dāng)您在調(diào)用中省略參數(shù)時(shí)會(huì)發(fā)生什么?函數(shù)內(nèi)部的參數(shù)變成undefined。

讓我們稍微修改前面的例子,只用一個(gè)參數(shù)調(diào)用函數(shù):

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

Tip 6: 給參數(shù)默認(rèn)值

有時(shí)函數(shù)不需要調(diào)用的全套參數(shù)。可以簡(jiǎn)單地為沒(méi)有值的參數(shù)設(shè)置默認(rèn)值。

看例子:

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

The function is invoked with a single argument multiply(5). Initially a parameter is 2 and b is undefined. The conditional statement verifies whether b is undefined. If it happens, b = 2 assignment sets a default value.

盡管提供了分配默認(rèn)值的方式,但我不建議直接比較’undefined’。它很冗長(zhǎng),看起來(lái)像一個(gè)黑客。

更好的方法是使用ES2015 [默認(rèn)參數(shù)](https://www.sitepoint.com/es6-default-parameters/)功能。 它很短,很有表現(xiàn)力,并且與’undefined`沒(méi)有直接的對(duì)比。

例子修改,添加默認(rèn)值:

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

ES2015的默認(rèn)參數(shù)功能非常直觀和高效。始終使用它來(lái)為可選參數(shù)設(shè)置默認(rèn)值。

2.4 函數(shù)返回值

隱式地,沒(méi)有return語(yǔ)句,JavaScript函數(shù)返回undefined。

在JavaScript中,沒(méi)有任何return語(yǔ)句的函數(shù)隱式地返回undefined:

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

square()函數(shù)不返回任何計(jì)算結(jié)果。函數(shù)調(diào)用結(jié)果是’未定義的’。

當(dāng)return語(yǔ)句存在時(shí)會(huì)發(fā)生同樣的情況,但是附近沒(méi)有表達(dá)式:

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

return;語(yǔ)句被執(zhí)行,但它不返回任何表達(dá)式。調(diào)用結(jié)果也是undefined。

當(dāng)然,在’return’附近表示要返回的表達(dá)式按預(yù)期工作:

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

Tip 7: 不要相信自動(dòng)分號(hào)插入

以下JavaScript語(yǔ)句列表必須以分號(hào)(;)結(jié)尾:

空的陳述 let,const,var,import,export聲明 表達(dá)式語(yǔ)句 調(diào)試器語(yǔ)句 繼續(xù)語(yǔ)句,break語(yǔ)句 拋出聲明 return語(yǔ)句

如果你使用上述語(yǔ)句之一,請(qǐng)務(wù)必在末尾指明分號(hào):

function getNum() { // Notice the semicolons at the end let num = 1; return num; } getNum(); // => 1

在let聲明和return聲明結(jié)尾處寫(xiě)了一個(gè)強(qiáng)制性分號(hào)。

當(dāng)你不想添加這些分號(hào)時(shí)會(huì)發(fā)生什么?例如減少源文件的大小。

在這種情況下,ECMAScript提供了[Automatic Semicolon Insertion](http://www.ecma-international.org/ecma-262/6.0/index.html#sec-automatic-semicolon-insertion)(ASI)機(jī)制,該機(jī)制可以插入 你丟失的分號(hào)。

在ASI的幫助下,你可以從前面的示例中刪除分號(hào):

function getNum() { // Notice that semicolons are missing let num = 1 return num } getNum() // => 1

以上文字是有效的JavaScript代碼。缺少的分號(hào)會(huì)自動(dòng)插入。

乍一看,它看起來(lái)很有希望。ASI機(jī)制讓你跳過(guò)不必要的分號(hào)。您可以使JavaScript代碼更小,更易于閱讀。

ASI有一個(gè)小而煩人的陷阱。當(dāng)一個(gè)換行符位于return和返回的表達(dá)式’return n expression之間時(shí),ASI自動(dòng)在換行符之前插入一個(gè)分號(hào); n表達(dá)式。

在函數(shù)內(nèi)部意味著什么return;語(yǔ)句?該函數(shù)返回undefined。如果您不詳細(xì)了解ASI的機(jī)制,那么意外返回的“未定義”是誤導(dǎo)性的。

例如,讓我們研究getPrimeNumbers()調(diào)用的返回值:

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

在return語(yǔ)句和數(shù)組文字表達(dá)式之間存在一個(gè)新行。 JavaScript在return后自動(dòng)插入一個(gè)分號(hào),解釋代碼如下:

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

語(yǔ)句return;使getPrimeNumbers()函數(shù)返回undefined而不是期望的數(shù)組。

通過(guò)刪除return和數(shù)組literal之間的換行符可以解決問(wèn)題:

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

我的建議是研究[確切地說(shuō)](http://www.bradoncode.com/blog/2015/08/26/javascript-semi-colon-insertion/) 自動(dòng)分號(hào)插入的作用,以避免這種情況。

Of course, never put a newline between return and the returned expression.

2.5 void 運(yùn)算

void運(yùn)算,計(jì)算一個(gè)表達(dá)式,不返回計(jì)算結(jié)果,所以返回值為undefined

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

[void use]運(yùn)算符的[一個(gè)用例](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/void#JavaScript_URIs)是將表達(dá)式評(píng)估抑制為undefined,依賴 關(guān)于評(píng)估的一些副作用。

3、數(shù)組中的undefined

You get when accessing an array element with an out of bounds index. 當(dāng)你試圖想要獲取一個(gè)超出數(shù)組界限范圍的下標(biāo)時(shí),會(huì)返回 undefined

const colors = [’blue’, ’white’, ’red’]; colors[5]; // => undefined colors[-1]; // => undefined

數(shù)組colors 有3個(gè)元素array has 3 elements, 對(duì)應(yīng)的下標(biāo)分別是 0, 1 and 2。 因?yàn)樵谠摂?shù)組中不存在下標(biāo)5和-1,所以當(dāng)你t訪問(wèn)colors[5] 和 colors[-1]會(huì)返回undefined.

在JavaScript中你可能遇到所謂的稀疏數(shù)組。這些是有間隙的數(shù)組,即在某些索引中沒(méi)有定義元素。

當(dāng)在一個(gè)稀疏數(shù)組中訪問(wèn)一個(gè)間隙(又名空槽)時(shí),你也會(huì)得到一個(gè)’undefined`。

以下示例將生成稀疏數(shù)組并嘗試訪問(wèn)其空插槽:

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

sparse1 是通過(guò)調(diào)用構(gòu)造函數(shù)“Array”構(gòu)造函數(shù)來(lái)創(chuàng)建的。它有3個(gè)空插槽。sparse2是用字面量的形式來(lái)創(chuàng)建了一個(gè)第二個(gè)元素為空的數(shù)組。在任何這些稀疏數(shù)組中,訪問(wèn)一個(gè)空插槽的結(jié)果都是“undefined”。

在處理數(shù)組時(shí),為了避免捕獲undefined,一定要使用有效的數(shù)組索引,并避免創(chuàng)建稀疏數(shù)組。

4、undefined and null 之間的不同

這里有個(gè)合理的問(wèn)題:undefined and null他們之間的主要區(qū)別是什么?都是一個(gè)指定值用來(lái)表示一個(gè)空狀態(tài)。

主要的區(qū)別是:undefined是用來(lái)表示一個(gè)變量的值沒(méi)有被定義。null 這是代表一個(gè)對(duì)象不存在。

我們來(lái)看一下這些區(qū)別:

當(dāng)變量number 被定義,但是沒(méi)有給它賦值進(jìn)行初始化:

let number; number; // => undefined

因此變量number的值為 undefined, .這明確表明了則是一個(gè)沒(méi)有初始化的變量

同樣的,當(dāng)你獲取一個(gè)對(duì)象存在的屬性時(shí),也會(huì)發(fā)生這樣的情況:該屬性未初始化。

const obj = { firstName: ’Dmitri’ }; obj.lastName; // => undefined

上面例子,因?yàn)?obj沒(méi)有l(wèi)astName屬性,所以JavaScript會(huì)把 obj.lastName 解析為 undefined.

還有另一種情況,當(dāng)一個(gè)變量期待是一個(gè)對(duì)象或者是一個(gè)方法返回一個(gè)對(duì)象時(shí),但是由于某些原因,你不能實(shí)例化一個(gè)對(duì)象。。那么這樣的情況下,null就會(huì)是一個(gè)有意義的指示器,來(lái)表示對(duì)象缺失。

例如:clone()` 是一個(gè)用來(lái)復(fù)制JavaScript對(duì)象的 函數(shù),這個(gè)函數(shù)期望能夠返回的是一個(gè)對(duì)象。

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

然后,可能會(huì)傳入一個(gè)不是對(duì)象的參數(shù):15,null。這種情況下,該函數(shù)就不能進(jìn)行對(duì)象復(fù)制,所以會(huì)返回 null -- 來(lái)表示對(duì)象缺失

typeof 運(yùn)算 能夠看出兩個(gè)值之間的區(qū)別

typeof undefined; // => ’undefined’ typeof null; // => ’object’

The 全等運(yùn)算符 === 對(duì)于undefined 和null,也顯示不相等。

let nothing = undefined; let missingObject = null; nothing === missingObject; // => false

5、總結(jié)

undefined的存在是JavaScript隨意性所造成的,它允許一下任意情況的使用:

uninitialized variables 未初始化的對(duì)象 non-existing object properties or methods 對(duì)象沒(méi)有的方法或?qū)傩? out of bounds indexes to access array elements 數(shù)組的超出長(zhǎng)度下標(biāo)的元素 the invocation result of a function that returns nothing 當(dāng)方法調(diào)用返回空時(shí)

大多數(shù)情況下,直接與’undefined’進(jìn)行比較是一種不好的做法,因?yàn)槟憧赡芤蕾囉谏厦嫣岬降脑试S但不鼓勵(lì)的做法。

一個(gè)有效的策略是減少代碼中未定義關(guān)鍵字的出現(xiàn)。在此期間,請(qǐng)總是以令人驚訝的方式記住它的潛在外觀,并通過(guò)應(yīng)用下列有益習(xí)慣來(lái)防止這種情況發(fā)生:

減少未初始化變量的使用 使變量生命周期變短并接近其使用的來(lái)源 盡可能為變量分配一個(gè)初始值 支持const,否則使用let 使用默認(rèn)值作為無(wú)意義的函數(shù)參數(shù) 驗(yàn)證屬性的存在或用缺省屬性填充不安全的對(duì)象 避免使用稀疏數(shù)組

到此這篇關(guān)于處理JavaScript值為undefined的7個(gè)小技巧的文章就介紹到這了,更多相關(guān)js值為undefined的技巧內(nèi)容請(qǐng)搜索好吧啦網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持好吧啦網(wǎng)!

標(biāo)簽: JavaScript
相關(guān)文章:
主站蜘蛛池模板: 亚洲精品久久久久午夜三 | 欧美巨大精品欧美一区二区 | 伊人色在线观看 | 久久综合狠狠综合久久综合88 | 久操免费在线视频 | 亚洲精品国产三级在线观看 | 欧洲一级毛片 | 国产大臿蕉香蕉大视频 | 美女视频永久黄网站免费观看韩国 | 国产一级做a爰片在线看免费 | 久久精品国产精品青草色艺 | 国内自拍在线视频高清 | 国产精品黄页在线播放免费 | 国产精品99在线观看 | 小明日韩在线看看永久区域 | 成人综合网址 | 日本一区二区高清免费不卡 | 欧美一级视频在线 | 香蕉福利久久福利久久香蕉 | 一级做a爱片特黄在线观看 一级做a爱片特黄在线观看免费看 | 国产一级毛片国产 | 久久99国产亚洲高清观看首页 | 欧美三级视频在线观看 | 久久欧洲视频 | a毛片免费播放全部完整 | 亚洲精品无码不卡 | 日本九六视频 | 九草在线免费观看 | www.亚洲成人.com | 成年人在线免费观看视频网站 | 成人一区二区免费中文字幕 | a级毛片毛片免费观看久潮喷 | 日韩美女一区二区三区 | 成人合集大片bd高清在线观看 | 久久视频这里只有精品 | 3级黄色 | 久久国产精品国产精品 | 黄色福利小视频 | 亚洲 欧美 国产 日韩 制服 bt | 韩国一级永久免费观看网址 | aaa大片 |