js常見問題總結概括

1、使用 typeof bar === "object" 來肯定 bar 是不是對象的潛在陷阱是什麼?如何避免這個陷阱?

首先typeof bar === "object"是檢測bar是不是對象的可靠方法,但在javascriptnull也被認爲是對象,所以如下代碼在控制檯中將輸出true:javascript

var bar = null;
console.log(typeof bar == "object"); 

因此知道了null的問題,同時檢測bar是不是null,就能夠避免這一問題啦:java

console.log((bar !== null) && (typeof bar === "object")); 

bar是一個數組的時候,例如,當var bar = []的時候;在不少狀況下,這是指望行爲,由於數字是真正的對象,但若是你想數組也返回false時,能夠修改上述方案:數組

console.log((bar !== null) && (typeof bar === "object") && (toString.call(bar) !== "[object Array]")); 

2、下面的代碼將輸出什麼到控制檯?爲何?

(function(){ var a = b = 3; })(); console.log(typeof a == "undefined"); console.log(typeof b == "undefined"); 

var a = b = 3;這句代碼等同於:b = 3; var a = b;這時候變量b是不加var聲明的變量,也就是全局變量,在函數內部沒有var聲明的變量是隱式全局變量。因此控制檯打印的結果爲:truefalse。 若是再深刻一步:在嚴格模式(使用use strict),結果又會怎樣? 在嚴格模式下運行的結果是:報錯:b is not undefined;這正是嚴格模式的特色,避免沒必要要的bug(避免全局變量污染)。安全

3、關於this的指向問題,如下代碼將會輸出什麼?

var myObject = {
    foo:"bar", func:function(){ var self = this; console.log(this.foo); console.log(self.foo); (function(){ console.log(this.foo); console.log(self.foo); }()); } }; myObject.func(); 

在外部函數中,thisself都是指向myObject,因此二者均可以正確的引用和訪問foo,在內部函數中,this再也不指向myObject,結果是this.foo沒有在內部函數中被定義。在ECMA5以前,在內部函數中的this將指向全局的window對象;反之,由於做爲ECMA5,內部函數中的功能this是未定義的。因此控制檯將輸出:bar ;bar ;undefined ;bar ;bash

4、use strict有什麼意義和好處?

use strict 是一種在JavaScript代碼運行時自動實行更嚴格解析和錯誤處理的方法。 嚴格模式的一些主要優勢包括:函數

1.使調試更加容易。那些被忽略或默默失敗了的代碼錯誤,會產生錯誤或拋出異常,所以儘早提醒你代碼中的問題,你才能更快地指引到它們的源代碼。測試

2.防止意外的全局變量。若是沒有嚴格模式,將值分配給一個未聲明的變量會自動建立該名稱的全局變量。這是JavaScript中最多見的錯誤之一。在嚴格模式下,這樣作的話會拋出錯誤。字體

3.消除this強制。若是沒有嚴格模式,引用null或未定義的值到this 值會自動強制到全局變量。這可能會致使許多使人頭痛的問題和讓人巴不得拔本身頭髮的bug。在嚴格模式下,引用 null或未定義的this值會拋出錯誤。ui

4.不容許重複的屬性名稱或參數值。當檢測到對象中重複命名的屬性,例如: var object = {foo: "bar", foo: "baz"};) 或檢測到函數中重複命名的參數時,例如: function foo(val1, val2, val1){}) 嚴格模式會拋出錯誤,所以捕捉幾乎能夠確定是代碼中的bug能夠避免浪費大量的跟蹤時間。this

5.使eval()更安全。在嚴格模式和非嚴格模式下,eval() 的行爲方式有所不一樣。最顯而易見的是,在嚴格模式下,變量和聲明在eval() 語句內部的函數不會在包含範圍內建立(它們會在非嚴格模式下的包含範圍中被建立,這也是一個常見的問題源)。

6.在delete使用無效時拋出錯誤。delete 操做符(用於從對象中刪除屬性)不能用在對象不可配置的屬性上。當試圖刪除一個不可配置的屬性時,非嚴格代碼將默默地失敗,而嚴格模式將在這樣的狀況下拋出異常。

5、當心javascript自動插入分號機制?看下面的代碼,它們會返回什麼?

function foo1(){ return { bar:"hello" }; } function foo2(){ return { bar:"hello" }; } console.log("foo1 returns:"); console.log(foo1()); consoel.log("foo2 returns:"); console.log(foo2()); 

以上代碼將會打印出:

foo1 returns:
Object {bar:"hello"} foo2 returns: undefined 

緣由是這樣的,當碰到 foo2()中包含return語句的代碼行(代碼行上沒有其餘任何代碼),分號會當即自動插入到返回語句以後。請仔細留意上面兩個函數中return的不一樣之處,foo2函數的return是單獨一行的。也不會拋出錯誤,由於代碼的其他部分是徹底有效的,即便它沒有獲得調用或作任何事情(至關於它就是是一個未使用的代碼塊,定義了等同於字符串"hello"的屬性 bar)。因此,在使用return語句的時候,要留意javascript的這個特色,儘量不要將return關鍵字寫在獨立的一行,避免沒必要形成沒必要要的錯誤。 在《JavaScript語言精粹》這本書裏,這個「自動插入分號」機制被劃入到了JavaScript的毒瘤裏面,與之並列的前面的全局變量。

6、NaN是什麼?如何測試一個值是否等於NaN

NaN屬性表明一個「不是數字」的值。這個特殊的值是由於運算不能執行而致使的,不能執行的緣由要麼是由於其中的運算對象之一非數字。例如:"abc" / 4,要麼是由於運算的結果非數字。例如:除數爲零。雖然NaN 意味着「不是數字」,可是它的類型,無論你信不信,是Number

console.log(typeof NaN === "number") // true 

此外, NaN 和任何東西比較,甚至是它本身自己,結果是false:

console.log(NaN == NaN)   // false 

一種半可靠的方法來測試一個數字是否等於NaN,是使用內置函數 isNaN(),但即便使用isNaN() 依然並不是是一個完美的解決方案。 一個更好的解決辦法是使用value !== value,若是值等於NaN,只會產生true。由於只有NaN 這貨,纔會本身不等於本身。 另外,ES6提供了一個新的Number.isNaN() 函數,這是一個不一樣的函數,而且比老的全局isNaN()函數更可靠。

7、如下代碼的運行結果是什麼?

1.console.log(1 + "2" + "2"); // "122";

2.console.log(1 + +"2" + "2"); // "32";

根據運算的順序,要執行的第一個運算是+"2"(第一個"2"前面的額外 +被視爲一元運算符),所以,JavaScript"2" 的類型轉換爲數字,而後應用一元 + 號(即將其視爲一個正數)。其結果就是獲得一個數字2

3.console.log(1 + -"1" + "2"); // "02";

4.console.log(+"1" + "1" + "2"); // "112";

5.console.log("a" - "b" + "2"); // "NaN2";

6.console.log("a" - "b" + 2); // NaN;

8、關於邏輯運算符,下面代碼的運行結果是什麼?

console.log( 0 || 1);   // 1;
console.log( 1 || 2);   // 1;
console.log( 0 && 1);   // 0;
console.log( 1 && 2);   // 2;

JavaScript中, ||&& 都是邏輯運算符,用於在從左至右計算時,返回第一個可徹底肯定的「邏輯值」。

9、如下代碼輸出的結果是什麼?爲何?

var a = {},
    b = {key:"b"}, c = {key:"c"}; a[b] = 123; a[c] = 456; console.log(a[b]); 

JavaScript在設置對象的屬性的時候,會暗中字符串化參數值;在以上代碼中bc都是對象,把它們設置爲對象a的參數,它們都將被轉換爲"[object Object]", 因此a[b]a[c]都至關於a['object Object'];因此a[c]會將a[b]的值覆蓋掉,所以,設置或引用a[c]和設置或引用a[b] 徹底相同。因此獲得的答案是 456

10、說明如下代碼的異同?

line-height:15px;
line-height:150%;
line-height:1.5;
line-height:1.5em;

行高爲150%時,會根據父元素的字體大小先計算出行高值而後再讓子元素繼承。因此當line-height:150%時,子元素的行高等於父元素的fontSize值 * 150%;

當line-height:1.5em時,會根據父元素的字體大小先計算出行高值而後再讓子元素繼承。因此當line-height:1.5em時,子元素的行高等於父元素的fontSize值 * 1.5em;

當line-height:1.5時,會根據子元素的字體大小動態計算出行高值讓子元素繼承。因此,當line-height:1.5時,子元素行高等於子元素的fontSize值 * 1.5 = 45px;若是沒有子元素,則以自身的fontSize值爲準

 

11、關於this指向,如下代碼將輸出什麼?

var person = {
    _name: 'I am John', sayHello: function (){ return this._name; } }; var sayHello = person.sayHello; console.log(sayHello()); console.log(person.sayHello()); 

代碼運行的結果是:

undefined
I am John

在執行sayHello()的時候,當訪問到this._name時,此時的this已經再也不是person 對象,而是全局窗口對象,也就是widnow對象。與此同時,widnow對象並不存在_name屬性,因此返回的是undefined

相關文章
相關標籤/搜索