問題還原
這是最近 cr 的時候在業務**中發現了乙個問題,先來看一下問題**:
// data 為介面返回的資料
const , total = 0 } = data.result || {};
const list = bizobject.list || ;
// 其他邏輯,比如把 list 更新到 state 中,等等
a 介面正常的情況:data 中有 result 屬性,且 result 物件中 bizobject 返回了乙個數—— ✅
b 介面異常:data 物件中沒有 result 屬性 —— ✅
c 介面異常:data 中有 result 屬性,result 物件中也有 bizobject 屬性,但是,bizobject 屬性的值是 null,然後呢?
從上下文來看,這位同學應該是期望解構賦值按以下方式執行:
const result = data.result || {};
const bizobject = result.bizobject || {};
但是,c 情形拋異常了:
uncaught typeerror: cannot read property 'list' of null
也就是 bizobject 的值是 null 而不是期望的 {}。為什麼呢?
解構賦值中的預設值
a variable can be assigned a default, in the case that the value unpacked from the object/array is undefined.
陣列、物件解構賦值時,只有當屬性(陣列索引對應的值)值為 undefined 時,才會使用預設值。
問題**中,當 bizobject 為 null 時,解構出來的就是 null,讀取 null 的 list 屬性,不報錯才怪。
函式預設引數
再來看看函式的預設引數是不是同樣的邏輯:
function dosomething(options = )
dosomething(undefined); //
dosomething(null); // null
不傳引數(隱式的 undefined)或者顯示地傳遞 undefined,使用了預設引數,傳 null 的時候沒有使用預設值,和解構賦值的預設值同樣的邏輯。
其實把上面的函式轉成 es5,就能直觀地了解其邏輯:
function dosomething() = ;
// 轉換成 es5
var _ref = {},
_ref$a = _ref.a,
a = _ref$a === void 0 ? 1 : _ref$a;
寫在最後
之所以會有同學把解構賦值預設值等同於 const bizobject = result.bizobject || {},可能是對 es6 的一些細節了解得不夠透徹,可以多翻翻文件:
還有乙個可能,前端同學並沒有誤解解構賦值預設值的工作原理,只是介面不規範引發了異常。一般而言,介面約定好欄位、型別後,就應該始終按約定的型別返回資料,約定的是物件,那沒有資料的時候也應該返回乙個空物件,即使不返回這個字段,前端也已經判斷了,莫名其妙地返回乙個 null 算哪門子事?
介面寫得有問題,有的人溝通一下還是會調整,有的人就始終一副「**不羈」樣子,通了就行,才不管你什麼規範、約定……對於不講究的人,還是自己多寫兩行**判斷一下,說多了也是浪費,***。
很多事情都是 100% 的期望,然後妥協,接受乙個差不多的結果。(bgm 差不多先生 - mc hot dog)
函式引數的預設值與解構賦值的預設值
function foo 物件,沒有預設值,只有解構賦值引數的預設值 console.log x,y foo undefined 5 foo 1 5 foo 1 2 foo typeerror cannot read property x of undefined上面 只使用了物件的解構賦值預設值,...
解構給預設值 ES6系列(二)解構賦值
之前在我們開發的過程中,難免會碰到這樣的問題 後端傳給我們一串資料,然後我們需要對這個資料進行處理。如果是這樣的乙個資料 let obj 然後我們需要用變數去儲存這些資料,那麼我們可能會這麼操作 let username obj.username,userid obj.userid,professi...
解構給預設值 ES6系列之解構賦值
我們之前談過了es6在變數宣告這一塊的小改動,忘了的同學可以戳藍字複習 前端初學者,也能輕鬆掌握es6 今天我們來 乙個新問題 之前在我們開發的過程中,難免會碰到這樣的情況 後端傳給我們一串資料,然後我們需要對這個資料進行處理。如果是這樣的乙個資料 let obj 然後我們需要用變數去儲存這些資料,...