做者:Dmitri Pavlutinjavascript
譯者:前端小智前端
點贊再看,養成習慣git
本文
GitHub
github.com/qq449245884… 上已經收錄,更多往期高贊文章的分類,也整理了不少個人文檔,和教程資料。歡迎Star和完善,你們面試能夠參照考點複習,但願咱們一塊兒有點東西。github
JS 的動態類型有好有壞。好的一面,沒必要指明變量的類型。很差的是,我們永遠沒法肯定變量的類型。面試
typeof
運算符能夠肯定 JS 中的6
種類型:正則表達式
typeof 10; // => 'number'
typeof 'Hello'; // => 'string'
typeof false; // => 'boolean'
typeof { a: 1 }; // => 'object'
typeof undefined; // => 'undefined'
typeof Symbol(); // => 'symbol'
複製代碼
一樣,instanceof
運算符用於檢測構造函數的 prototype
屬性是否出如今某個實例對象的原型鏈上。數組
class Cat { }
const myCat = new Cat();
myCat instanceof Cat; // => true
複製代碼
可是typeof
和instanceof
的一些行爲可能會使人混淆。防範於未然,我們須要提早了解一些邊緣狀況。promise
typeof myObject === 'object'
會告知myObject
是不是一個對象類型。舉個例子:函數
const person = { name: '前端小智' };
typeof person; // => 'object'
複製代碼
typeof person
是'object'
,由於person
是一個普通的 JS 對象。
在某場景下,變量值可能須要指定爲 null
,下面是一些場景:
可使用null
來跳過指示配置對象
使用null
初始化稍後要保存對象的變量
當函數因爲某種緣由沒法構造對象時,返回null
例如,若是不存在正則表達式匹配項,則str.match(regExp)
方法返回null
:
const message = 'Hello';
message.match(/Hi/); // => null
複製代碼
這裏引出一個問題,可使用typeof 來區分有值的對象和具備 null
值的對象嗎?
let myObject = null;
typeof myObject; // => 'object'
myObject = { prop: 'Value' };
typeof myObject; // => 'object'
複製代碼
從上面能夠看出,typeof
對象有值的對象和具備 null
值的對象,獲得的結果都是'object'。
能夠以下面方法來檢測變量是否有對象且不是null
:
function isObject(value) {
return typeof value === 'object' && value !== null;
}
isObject({}); // => true
isObject(null); // => false
複製代碼
除了檢查value
是否爲object
: typeof value === 'object'
以外,還須要明確地驗證null
: value !== null
。
若是試圖檢測一個變量是否包含一個數組,常見的錯誤就是使用typeof
操做符:
const colors = ['white', 'blue', 'red'];
typeof colors; // => 'object'
複製代碼
檢測數組的正確方法是使用Array.isArray()
:
const colors = ['white', 'blue', 'red'];
const hero = { name: 'Batman' };
Array.isArray(colors); // => true
Array.isArray(hero); // => false
複製代碼
Array.isArray(colors)
返回一個布爾值true
,表示colors
是一個數組。
JS中的undefined
是一個特殊值,表示未初始化的變量。
若是試圖訪問未初始化的變量、不存在的對象屬性,則獲取到的值爲 undefined
:
let city;
let hero = { name: '前端小智', villain: false };
city; // => undefined
hero.age; // => undefined
複製代碼
訪問未初始化的變量 city
和不存在的屬性hero.age
的結果爲undefined
。
要檢查屬性是否存在,能夠在條件中使用object[propName]
,這種遇到值爲虛值或者undefined
是不可靠的:
function getProp(object, propName, def) {
// 錯誤方式
if (!object[propName]) {
return def;
}
return object[propName];
}
const hero = { name: '前端小智', villain: false };
getProp(hero, 'villain', true); // => true
hero.villain; // => false
複製代碼
若是對象中不存在propName
,則object [propName]
的值爲undefined
。 if (!object[propName]) { return def }
保護缺乏的屬性。
hero.villain
屬性存在且值爲false
。 可是,該函數在訪問villan
值時錯誤地返回true
:getProp(hero, 'villain', true)
undefined
是一個虛值,一樣false
、0
和''
和null
。
不要使用虛值做爲類型檢查,而是要明確驗證屬性是否存在於對象中:
typeof object[propName] === 'undefined'
propName in object
object.hasOwnProperty(propName)
接着,我們來改進getProp()
函數:
function getProp(object, propName, def) {
// Better
if (!(propName in object)) {
return def;
}
return object[propName];
}
const hero = { name: '前端小智', villain: false };
getProp(hero, 'villain', true); // => false
hero.villain; // => false
複製代碼
if (!(propName in object)) { ... }
條件正確肯定屬性是否存在。
我認爲最好避免使用邏輯運算符||
做爲默狀況,這個容易打斷閱讀的流程:
const hero = { name: '前端小智', villain: false };
const name = hero.name || 'Unknown';
name; // => '前端小智'
hero.name; // => '前端小智'
// 很差方式
const villain = hero.villain || true;
villain; // => true
hero.villain; // => false
複製代碼
hero
對象存在屬性villain
,值爲 false
,可是表達式hero.villain || true
結果爲true
。
邏輯操做符||
用做訪問屬性的默認狀況,當屬性存在且具備虛值時,該操做符沒法正確工做。
若要在屬性不存在時默認設置,更好的選擇是使用新的**雙問號(??)**操做符,
const hero = { name: '前端小智', villan: false };
// 好的方式
const villain = hero.villain ?? true;
villain; // => false
hero.villain; // => false
複製代碼
或使用解構賦值:
const hero = { name: '前端小智', villain: false };
// Good
const { villain = true } = hero;
villain; // => false
hero.villain; // => false
複製代碼
整數,浮點數,特殊數字(例如Infinity
,NaN
)的類型均爲數字。
typeof 10; // => 'number'
typeof 1.5; // => 'number'
typeof NaN; // => 'number'
typeof Infinity; // => 'number'
複製代碼
NaN
是在沒法建立數字時建立的特殊數值。NaN
是not a number
的縮寫。
在下列狀況下不能建立數字:
Number('oops'); // => NaN
5 * undefined; // => NaN
Math.sqrt(-1); // => NaN
NaN + 10; // => NaN
複製代碼
因爲NaN
,意味着對數字的操做失敗,所以對數字有效性的檢查須要額外的步驟。
下面的isValidNumber()
函數也能夠防止NaN
致使的錯誤:
function isValidNumber(value) {
// Good
return typeof value === 'number' && !isNaN(value);
}
isValidNumber(Number('Z99')); // => false
isValidNumber(5 * undefined); // => false
isValidNumber(undefined); // => false
isValidNumber(Number('99')); // => true
isValidNumber(5 + 10); // => true
複製代碼
除了typeof value === 'number'
以外,還多驗證!isNaN(value)
確保萬無一失。
JS 中的每一個對象都引用一個特殊的函數:對象的構造函數。
object instanceof Constructor
是用於檢查對象的構造函數的運算符:
const object = {};
object instanceof Object; // => true
const array = [1, 2];
array instanceof Array; // => true
const promise = new Promise(resolve => resolve('OK'));
promise instanceof Promise; // => true
複製代碼
如今,我們定義一個父類Pet
和它的子類Cat
:
class Pet {
constructor(name) {
this.name;
}
}
class Cat extends Pet {
sound = 'Meow';
}
const myCat = new Cat('Scratchy');
複製代碼
如今,嘗試肯定myCat
的實例
myCat instanceof Cat; // => true
myCat instanceof Pet; // => true
myCat instanceof Object; // => true
複製代碼
instanceof
運算符表示myCat
是Cat
,Pet
甚至Object
的實例。
instanceof
操做符經過整個原型鏈搜索對象的構造函數。要準確地檢測建立對象的構造函數,須要檢測 constructor
屬性
myCat.constructor === Cat; // => true
myCat.constructor === Pet; // => false
myCat.constructor === Object; // => false
複製代碼
只有myCat.constructor === Cat
的計算結果爲true
,表示 Cat
是 myCat
實例的構造函數。
運算符typeof
和instanceof
用於類型檢查。 它們儘管易於使用,但須要注意一些特殊狀況。
須要注意的是:typeof null
等於'object'
。 要肯定變量是否包含非null
對象,須要顯示指明null
:
typeof myObject === 'object' && myObject !== null
複製代碼
檢查變量是否包含數組的最佳方法是使用Array.isArray(variable)
內置函數。
由於undefined
是虛值的,因此咱們常常直接在條件句中使用它,但這種作法容易出錯。更好的選擇是使用prop in object
來驗證屬性是否存在。
使用雙問號操做系符號object.prop ?? def
或者 { prop = def } = object
來訪問可能丟失的屬性。
NaN
是一個類型爲number
的特殊值,它是由對數字的無效操做建立的。爲了確保變量有正確的數字,最好使用更詳細的驗證:!isNaN(number) && typeof number === 'number'
。
最後,請記住instanceof
經過prototype
鏈搜索實例的構造函數。若是不知道這一點,那麼若是使用父類驗證子類實例,可能會獲得錯誤的結果。
代碼部署後可能存在的BUG無法實時知道,過後爲了解決這些BUG,花了大量的時間進行log 調試,這邊順便給你們推薦一個好用的BUG監控工具 Fundebug。
原文:dmitripavlutin.com/javascript-…
乾貨系列文章彙總以下,以爲不錯點個Star,歡迎 加羣 互相學習。
我是小智,公衆號「大遷世界」做者,對前端技術保持學習愛好者。我會常常分享本身所學所看的乾貨,在進階的路上,共勉!
關注公衆號,後臺回覆福利,便可看到福利,你懂的。