undefined的知識

1.undefined如何出現express

對於JavaScript,解釋器在訪問還沒有初始化的變量或對象屬性時返回undefined;函數沒有返回值,是undefined數組

2.null如何出現安全

null表示缺乏的對象引用,JS自己不會將變量或對象屬性設置爲null;函數

一些原生方法,好比String.prototype.match(),能夠返回null來表示丟失的對象。ui

3.常出現的錯誤:es5

TypeError: 'undefined' is not a functionspa

TypeError: Cannot read property 'xxx' of undefinedprototype

type errorsdebug

4.undefinedcode

1.)未爲變量賦值時默認值爲undefined

該標準明肯定義,當訪問未初始化的變量、不存在的對象屬性、不存在的數組元素等時,將接收到一個undefined 的值

2.)Undefined type是其惟一值爲undefined 值的類型

typeof undefined返回「undefined」字符串

console.log(typeof undefined) //字符串undefined
console.log(typeof undefined ==="undefined") //true

let a;

typeof a=== "undefined"; // => true

3.)致使undefined的常見場景

(1).未初始化變量

myVariable已聲明,但還沒有賦值,默認值爲undefined

解決未初始化變量問題的有效方法是儘量分配初始值。 變量在未初始化狀態中越少越好。

技巧1:使用 let 和 const 來代替 var

技巧2:技巧2:增長內聚性

內聚描述模塊的元素(命名空間、類、方法、代碼塊)內聚在一塊兒的程度。凝聚力的測量一般被稱爲高凝聚力或低內聚。

(2). 訪問不存在的屬性

訪問不存在的對象屬性時,JS 返回undefined

let tuandui = {
title: 'bitt uit'
};
console.log(tuandui.alis) // => undefined

修改後:自己訪問不存在的屬性不會引起錯誤, 但嘗試從不存在的屬性值中獲取數據時就會出現問題。 常見的的錯誤是 TypeError: Cannot read property <prop> of undefined

eg:

let tuandui = {
title: 'bitt uit'
};
tuandui.alis[0]
console.log(tuandui.alis[0]) // => Uncaught TypeError: Cannot read property '0' of undefined

JS 容許訪問不存在的屬性,這種容許訪問的特性容易引發混淆:可能設置了屬性,也可能沒有設置屬性,繞過這個問題的理想方法是限制對象始終定義它所持有的屬性。

不幸的是,我們經常沒法控制對象

技巧3:檢查屬性是否存在

JS 提供了許多方法來肯定對象是否具備特定屬性:

  • obj.prop!== undefined:直接與undefined進行比較

  • typeof obj.prop!=='undefined':驗證屬性值類型

  • obj.hasOwnProperty('prop'):驗證對象是否具備本身的屬性

  • 'prop' in obj:驗證對象是否具備本身的屬性或繼承屬性

建議使用 in 操做符。in操做符的存在代表一個明確的意圖,即檢查對象是否具備特定的屬性,而不訪問實際的屬性值。

obj.hasOwnProperty('prop')也是一個很好的解決方案,它比 in 操做符稍長,僅在對象本身的屬性中進行驗證。

涉及與undefined進行比較剩下的兩種方式可能有效,obj.prop!== undefinedtypeof obj.prop!=='undefined'看起來冗長。

經過in的實例:

function addTo(array, toAppend) {
const arrayCopy = array.slice();
if ('first' in toAppend) {
arrayCopy.unshift(toAppend.first);
}
if ('last' in toAppend) {
arrayCopy.push(toAppend.last);
}
return arrayCopy;
}
addTo([1,2,3], {
last:4
});
console.log(addTo([1,2,3], {
last: 4
})) //[0, 1, 2, 3, 4]
addTo([10], {
first: 0,
last: false
});
console.log(addTo([10], {
first: 0,
last: false
})) //[0, 10, false]

技巧4:解構訪問對象屬性

在訪問對象屬性時,若是屬性不存在,有時須要指示默認值。可使用in和三元運算符來實現這一點。

eg:

const thatobj = {};
const prop = 'prop' in thatobj ? thatobj.prop : 'default';
prop; // => 'default'
console.log(prop)

對象解構:對象解構容許將對象屬性值直接提取到變量中,並在屬性不存在時設置默認值,避免直接處理undefined 

const thatobj = {};
const {
ab = 'defaults'
} = thatobj;
ab; //
console.log(ab) //=> 'defaults'

eg:

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: '*'
});
console.log(quote('Hello World', {
char: '*'
}))// => '*Hello World*'
quote('Goods day');
console.log(quote('Goods day'))// => "Goods day"

 技巧5: 用默認屬性填充對象

 若是不須要像解構賦值那樣爲每一個屬性建立變量,那麼丟失某些屬性的對象能夠用默認值填充。

ES6 Object.assign(target,source1,source2,...)將全部可枚舉的自有屬性的值從一個或多個源對象複製到目標對象中,該函數返回目標對象。

例如,須要訪問unsafes對象的屬性,該對象並不老是包含其完整的屬性集。

爲了不從unsafes訪問不存在的屬性,讓咱們作一些調整:

定義包含默認屬性值的defaults對象

調用Object.assign({},defaults,unsafes)來構建新的對象options。 新對象從unsafes接收全部屬性,但缺乏的屬性從defaults對象獲取。

eg:

const unsafe = {
fontSize:60
};
const defaults = {
fontSize: 100,
color: 'white'
};
const options = Object.assign({}, defaults, unsafe);
options.fontSize;
console.log(options.fontSize)// => 60
options.color;
console.log(options.color)// => 'white'

枚舉源對象的順序很重要:後面的源對象屬性會覆蓋前面的源對象屬性。

還有一種簡單的方法就是使用ES6中展開運算符:

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

對象初始值設定項從defaultsunsafeOptions源對象擴展屬性。 指定源對象的順序很重要,後面的源對象屬性會覆蓋前面的源對象。

使用默認屬性值填充不完整的對象是使代碼安全且持久的有效策略。不管哪一種狀況,對象老是包含完整的屬性集:而且沒法生成undefined的屬性。

(3). 函數參數

函數參數隱式默認爲undefined

一般,用特定數量的參數定義的函數應該用相同數量的參數調用。在這種狀況下,參數獲得指望的值

function multip(a, b) {
a; // => 5
b; // => 3
return a * b;
}
multip(2, 3); // => 6

調用multip(5,3)使參數ab接收相應的53值,返回結果:5 * 3 = 15

在調用時省略參數會發生什麼?

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

函數multip(a, b){}由兩個參數ab定義。調用multip(5)用一個參數執行:結果一個參數是2,可是b參數是undefined

技巧6: 使用默認參數值

//技巧6: 使用默認參數值
//es5
function mult(a1, b1) {
if (b1 === undefined) {
b1 = 100;
}
return a1 * b1;
}
mult(5);
console.log(mult(10)) // => 50

function mult(a1, b1) {
if (b1 === undefined) {
b1 = 100;
}
return a1 * b1;
}
mult(5);
console.log(mult(10)) // => 50
//雖然所提供的分配默認值的方法有效,但不建議直接與undefined值進行比較。它很冗長

//這裏可使用 ES6 的默認值:
function mults(a, b = 100) {
return a * b;
}
mults(50);
console.log(mults(50))// => 5000
mults(50, undefined);
console.log(mults(50, undefined))// => 5000

(4).函數返回值

 沒有return語句,JS 函數返回undefined

在JS中,沒有任何return語句的函數隱式返回undefined

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

square() 函數沒有返回計算結果,函數調用時的結果undefined

return語句後面沒有表達式時,默認返回 undefined

function squares(x) {
const res = x * x;
return;
}
squares(10);
console.log(squares(2))// => undefined

return; 語句被執行,但它不返回任何表達式,調用結果也是undefined

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

技巧7: 不要相信自動插入分號

JS 中的如下語句列表必須以分號(;)結尾:

空語句

letconstvarimportexport聲明

表達語句

debugger 語句

continue 語句,break 語句

throw 語句

return 語句

若是使用上述聲明之一,請儘可能務必在結尾處指明分號

let 聲明和 return 語句結束時,強制性寫分號。

固然,不要在return和返回的表達式之間放置換行符。

(5).void 操做符

void <expression>計算表達式不管計算結果如何都返回undefined 。

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

void操做符的一個用例是將表達式求值限制爲undefined,這依賴於求值的一些反作用。

(6).未定義數組

訪問越界索引的數組元素時,會獲得undefined 。

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

colors數組有3個元素,所以有效索引爲012

由於索引5-1沒有數組元素,因此訪問colors[5]colors[-1]值爲undefined

JS 中,可能會遇到所謂的稀疏數組。這些數組是有間隙的數組,也就是說,在某些索引中,沒有定義元素。

當在稀疏數組中訪問間隙(也稱爲空槽)時,也會獲得一個undefined

下面的示例生成稀疏數組並嘗試訪問它們的空槽

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

使用數組時,爲了不獲取undefined,請確保使用有效的數組索引並避免建立稀疏數組。

4).undefined和null之間的區別

undefinednull之間的主要區別是什麼?這兩個特殊值都表示爲空狀態。

主要區別在於undefined表示還沒有初始化的變量的值,null表示故意不存在對象。

number 定義了但沒有賦值。

let number;
number; // => undefined

number 變量未定義,這清楚地代表未初始化的變量。

當訪問不存在的對象屬性時,也會發生相同的未初始化概念

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

由於obj中不存在lastName屬性,因此JS正確地將obj.lastName計算爲undefined

在其餘狀況下,你知道變量指望保存一個對象或一個函數來返回一個對象。可是因爲某些緣由,你不能實例化該對象。在這種狀況下,null是丟失對象的有意義的指示器。

例如,clone()是一個克隆普通JS對象的函數,函數將返回一個對象

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

typeof操做符區分了這兩個值

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

嚴格相等運算符===能夠正確區分undefinednull

let nothing = undefined;let missingObject = null;nothing === missingObject; // => false
相關文章
相關標籤/搜索