久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

37個JavaScript基本面試問題和解答

 heii2 2018-08-12


1,、使用typeof bar ===“object”來確定bar是否是一個對象時有什么潛在的缺陷?這個陷阱如何避免,?

盡管typeof bar ===“object”是檢查bar是否是對象的可靠方法,,但JavaScript中令人驚訝的問題是null也被認為是一個對象,!

因此,對于大多數(shù)開發(fā)人員來說,,下面的代碼會將真實(而不是錯誤)記錄到控制臺:

var bar = null;console.log(typeof bar === 'object');
 // logs true!

只要知道這一點,就可以通過檢查bar是否為空來輕松避免該問題:

console.log((bar !== null) && (typeof bar === 'object')); 
 // logs false

為了在我們的答案更加的完整,,還有兩件事值得注意:

首先,,如果bar是一個函數(shù),上面的解決方案將返回false,。在大多數(shù)情況下,,這是所期望的行為,但是在您希望函數(shù)返回true的情況下,,您可以將上述解決方案修改為:

console.log((bar !== null) && ((typeof bar === 'object') || (typeof bar === 'function')));

其次,,如果bar是數(shù)組,,則上述解決方案將返回true(例如,如果var bar = [];),。在大多數(shù)情況下,,這是所希望的行為,因為數(shù)組確實是對象,,但是在您想要對數(shù)組也是false的情況下,,可以將上述解決方案修改為:

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

但是,還有一個替代方法對空值,,數(shù)組和函數(shù)返回false,,但對于對象則為true:

console.log((bar !== null) && (bar.constructor === Object));

或者,如果您使用jQuery:

console.log((bar !== null) && (typeof bar === 'object') && (! $.isArray(bar)));

ES5使得數(shù)組的情況非常簡單,,包括它自己的空檢查:

console.log(Array.isArray(bar));


2,、下面的代碼將輸出到控制臺的是什么,為什么,?

(function(){
 var a = b = 3;})();
 console.log('a defined? ' + (typeof a !== 'undefined'));
 console.log('b defined? ' + (typeof b !== 'undefined'));

由于a和b都在函數(shù)的封閉范圍內(nèi)定義,,并且由于它們所在的行以var關鍵字開頭,因此大多數(shù)JavaScript開發(fā)人員會希望typeof a和typeof b在上面的示例中都未定義,。

但是,,情況并非如此。這里的問題是大多數(shù)開發(fā)人員錯誤地理解語句var a = b = 3;以下簡寫為:

var b = 3;var a = b;

但實際上,,var a = b = 3;其實是速記:

b = 3;var a = b;

因此(如果您不使用嚴格模式),,代碼片段的輸出將為:

a defined? falseb defined? true

但是如何在封閉函數(shù)的范圍之外定義b?那么,,因為聲明var a = b = 3;是語句b = 3的簡寫;并且var a = b; b最終成為一個全局變量(因為它不在var關鍵字后面),,因此它仍然在作用域內(nèi),即使在封閉函數(shù)之外,。

注意,,在嚴格模式下(即,使用strict),,語句var a = b = 3;會產(chǎn)生一個ReferenceError的運行時錯誤:b沒有定義,,從而避免了可能導致的任何頭headfakes/bugs。 (這就是為什么你應該在你的代碼中使用strict,,一個重要的例子?。?/span>

3、下面的代碼將輸出到控制臺的是什么,?,,為什么?

var myObject = {    
foo: 'bar',    func: function() {
       var self = this;        
       console.log('outer func:  this.foo = ' + this.foo);    
          console.log('outer func:  self.foo = ' + self.foo);        (function() {          
            console.log('inner func:  this.foo = ' + this.foo);    
            console.log('inner func:  self.foo = ' + self.foo);        }());    }};myObject.func();

以上代碼將輸出到控制臺:

outer func:  this.foo = barouter func:  
self.foo = bar
inner func:  
this.foo = undefined
inner func:
 self.foo = bar

在外部函數(shù)中,this和self都引用myObject,,因此都可以正確地引用和訪問foo,。

但在內(nèi)部函數(shù)中,這不再指向myObject,。因此,,this.foo在內(nèi)部函數(shù)中是未定義的,而對局部變量self的引用仍然在范圍內(nèi)并且可以在那里訪問,。

4,、在功能塊中封裝JavaScript源文件的全部內(nèi)容的重要性和原因是什么?

這是一種日益普遍的做法,,被許多流行的JavaScript庫(jQuery,,Node.js等)所采用。這種技術在文件的全部內(nèi)容周圍創(chuàng)建一個閉包,,這可能最重要的是創(chuàng)建一個私有名稱空間,,從而有助于避免不同JavaScript模塊和庫之間的潛在名稱沖突。

這種技術的另一個特點是為全局變量提供一個容易引用(可能更短)的別名,。例如,,這通常用于jQuery插件。 

jQuery允許您使用jQuery.noConflict()來禁用對jQuery名稱空間的$引用,。如果這樣做了,,你的代碼仍然可以使用$使用閉包技術,如下所示:

(function($) {
/* jQuery plugin code referencing $ */
} )
(jQuery);


5,、在JavaScript源文件的開頭包含'use strict'的意義和有什么好處,?

這里最簡單也是最重要的答案是use strict是一種在運行時自動執(zhí)行更嚴格的JavaScript代碼解析和錯誤處理的方法

如果代碼錯誤被忽略或失敗,,將會產(chǎn)生錯誤或拋出異常,。總的來說,,這是一個很好的做法,。

嚴格模式的一些主要優(yōu)點包括:

  • 使調(diào)試更容易。 如果代碼錯誤本來會被忽略或失敗,,那么現(xiàn)在將會產(chǎn)生錯誤或拋出異常,,從而更快地發(fā)現(xiàn)代碼中的問題,并更快地指引它們的源代碼,。

  • 防止意外全局,。 如果沒有嚴格模式,將值賦給未聲明的變量會自動創(chuàng)建一個具有該名稱的全局變量,。這是JavaScript中最常見的錯誤之一。在嚴格模式下,,嘗試這樣做會引發(fā)錯誤,。

  • 消除隱藏威脅,。在沒有嚴格模式的情況下,對null或undefined的這個值的引用會自動強制到全局,。這可能會導致許多headfakespull-out-your-hair類型的錯誤,。在嚴格模式下,引用null或undefined的這個值會引發(fā)錯誤,。

  • 不允許重復的參數(shù)值,。 嚴格模式在檢測到函數(shù)的重復命名參數(shù)(例如,函數(shù)foo(val1,,val2,,val1){})時會引發(fā)錯誤,從而捕獲代碼中幾乎可以肯定存在的錯誤,,否則您可能會浪費大量的時間追蹤,。

    • 注意:它曾經(jīng)是(在ECMAScript 5中)strict模式將禁止重復的屬性名稱(例如var object = {foo:“bar”,foo:“baz”};)但是從ECMAScript 2015 開始,,就不再有這種情況了,。

  • 使eval()更安全。 eval()在嚴格模式和非嚴格模式下的行為方式有些不同,。最重要的是,,在嚴格模式下,在eval()語句內(nèi)部聲明的變量和函數(shù)不會在包含范圍中創(chuàng)建(它們是以非嚴格模式在包含范圍中創(chuàng)建的,,這也可能是問題的常見來源),。

  • 拋出無效的使用錯誤的刪除符。 刪除操作符(用于從對象中刪除屬性)不能用于對象的不可配置屬性,。當試圖刪除一個不可配置的屬性時,,非嚴格代碼將自動失敗,而在這種情況下,,嚴格模式會引發(fā)錯誤,。


6、考慮下面的兩個函數(shù),。他們都會返回同樣的值嗎,?為什么或者為什么不?

function foo1(){  return {      bar: 'hello'  };}function foo2(){  return  {      bar: 'hello'  };}

令人驚訝的是,,這兩個函數(shù)不會返回相同的結果,。而是:

console.log('foo1 returns:');console.log(foo1());console.log('foo2 returns:');console.log(foo2());

會產(chǎn)生:

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

這不僅令人驚訝,而且特別令人煩惱的是,,foo2()返回未定義而沒有引發(fā)任何錯誤,。

原因與JavaScript中分號在技術上是可選的事實有關(盡管忽略它們通常是非常糟糕的形式)。因此,在foo2()中遇到包含return語句的行(沒有其他內(nèi)容)時,,會在return語句之后立即自動插入分號,。

由于代碼的其余部分是完全有效的,即使它沒有被調(diào)用或做任何事情(它只是一個未使用的代碼塊,,它定義了一個屬性欄,,它等于字符串“hello”),所以不會拋出任何錯誤,。

這種行為也被認為是遵循了在JavaScript中將一行開頭大括號放在行尾的約定,,而不是在新行的開頭。如此處所示,,這不僅僅是JavaScript中的一種風格偏好,。


7、什么是NaN,?它的類型是什么,?如何可靠地測試一個值是否等于NaN?

NaN屬性表示“不是數(shù)字”的值,。這個特殊值是由于一個操作數(shù)是非數(shù)字的(例如“abc”/ 4)或者因為操作的結果是非數(shù)字而無法執(zhí)行的,。

雖然這看起來很簡單,但NaN有一些令人驚訝的特征,,如果人們沒有意識到這些特征,,就會導致bug。

一方面,,雖然NaN的意思是“不是數(shù)字”,,但它的類型是,數(shù)字:

console.log(typeof NaN === 'number');  
// logs 'true'

此外,,NaN相比任何事情 - 甚至本身,! - 是false:

console.log(NaN === NaN);
 // logs 'false'

測試數(shù)字是否等于NaN的半可靠方法是使用內(nèi)置函數(shù)isNaN(),但即使使用isNaN()也不是一個好的解決方案,。.

一個更好的解決方案要么是使用value,!==值,如果該值等于NaN,,那么只會生成true,。另外,ES6提供了一個新的Number.isNaN()函數(shù) ,,它與舊的全局isNaN()函數(shù)不同,,也更加可靠。

8,、下面的代碼輸出什么,?解釋你的答案,。

console.log(0.1 + 0.2);console.log(0.1 + 0.2 == 0.3);

對這個問題的一個有教養(yǎng)的回答是:“你不能確定。它可能打印出0.3和true,,或者可能不打印,。 JavaScript中的數(shù)字全部用浮點精度處理,因此可能不會總是產(chǎn)生預期的結果,。“

上面提供的示例是演示此問題的經(jīng)典案例,。令人驚訝的是,,它會打印出來:

0.30000000000000004false

一個典型的解決方案是比較兩個數(shù)字與特殊常數(shù)Number.EPSILON之間的絕對差值:

function areTheNumbersAlmostEqual(num1, num2) { 
   return Math.abs( num1 - num2 ) <>Number.EPSILON;}console.log(areTheNumbersAlmostEqual(0.1 + 0.2, 0.3));

討論寫函數(shù)的可能方法isInteger(x),它確定x是否是一個整數(shù),。

這聽起來很平凡,,事實上,ECMAscript 6為此正好引入了一個新的Number.isInteger()函數(shù),,這是微不足道的,。但是,在ECMAScript 6之前,,這有點復雜,,因為沒有提供與Number.isInteger()方法等價的方法。

問題在于,,在ECMAScript規(guī)范中,,整數(shù)只在概念上存在;即數(shù)值始終作為浮點值存儲。

考慮到這一點,,最簡單,,最清潔的ECMAScript-6之前的解決方案(即使將非數(shù)字值(例如字符串或空值)傳遞給該函數(shù),該解決方案也具有足夠的可靠性以返回false)將成為以下用法按位異或運算符:

function isInteger(x) { return (x ^ 0) === x; }

下面的解決方案也可以工作,,盡管不如上面那樣高雅

function isInteger(x) { return Math.round(x) === x; }

請注意,,在上面的實現(xiàn)中Math.ceil()或Math.floor()可以同樣使用(而不是Math.round())。

或者:

function isInteger(x) {
return (typeof x === 'number') && (x % 1 === 0);
}

一個相當常見的不正確的解決方案如下:

function isInteger(x) { 
return parseInt(x, 10) === x;
}

雖然這個基于parseInt的方法對許多x值很有效,,但一旦x變得相當大,,它將無法正常工作。問題是parseInt()在解析數(shù)字之前將其第一個參數(shù)強制轉(zhuǎn)換為字符串,。因此,,一旦數(shù)字變得足夠大,其字符串表示將以指數(shù)形式呈現(xiàn)(例如1e + 21),。因此,,parseInt()將嘗試解析1e + 21,但是當它到達e字符時將停止解析,,因此將返回值1.觀察:

> String(1000000000000000000000)'1e+21'
> parseInt(1000000000000000000000, 10)1
> parseInt(1000000000000000000000, 10) === 1000000000000000000000false

9,、執(zhí)行下面的代碼時,,按什么順序?qū)?shù)字1-4記錄到控制臺?為什么,?

(function() {    console.log(1);     setTimeout(function(){console.log(2)}, 1000);     setTimeout(function(){console.log(3)}, 0);     console.log(4);})();

這些值將按以下順序記錄:

1432

我們先來解釋一下這些可能更為明顯的部分:

  • 首先顯示1和4,,因為它們是通過簡單調(diào)用console.log()而沒有任何延遲記錄的

  • 在3之后顯示,因為在延遲1000毫秒(即1秒)之后記錄2,,而在0毫秒的延遲之后記錄3,。

好的。但是,,如果在延遲0毫秒后記錄3,,這是否意味著它正在被立即記錄?而且,,如果是這樣,,不應該在4之前記錄它,因為4是由后面的代碼行記錄的嗎,?

答案與正確理解JavaScript事件和時間有關,。 .

瀏覽器有一個事件循環(huán),它檢查事件隊列并處理未決事件,。例如,,如果在瀏覽器繁忙時(例如,處理onclick)在后臺發(fā)生事件(例如腳本onload事件),,則該事件被附加到隊列中,。當onclick處理程序完成時,將檢查隊列并處理該事件(例如,,執(zhí)行onload腳本),。

同樣,如果瀏覽器繁忙,,setTimeout()也會將其引用函數(shù)的執(zhí)行放入事件隊列中,。

當值為零作為setTimeout()的第二個參數(shù)傳遞時,它將嘗試“盡快”執(zhí)行指定的函數(shù),。具體來說,,函數(shù)的執(zhí)行放置在事件隊列中,以在下一個計時器滴答時發(fā)生,。但請注意,,這不是直接的;該功能不會執(zhí)行,直到下一個滴答聲,。這就是為什么在上面的例子中,,調(diào)用console.log(4)發(fā)生在調(diào)用console.log(3)之前(因為調(diào)用console.log(3)是通過setTimeout調(diào)用的,所以稍微延遲了一點),。


10,、編寫一個簡單的函數(shù)(少于160個字符),,返回一個布爾值,指示字符串是否是palindrome,。

如果str是回文,,以下一行函數(shù)將返回true;否則,它返回false,。

function isPalindrome(str) {  
str = str.replace(/\W/g, '').toLowerCase();  
return (str == str.split('').reverse().join(''));}

例如:

console.log(isPalindrome('level'));                  
// logs 'true'console.log(isPalindrome('levels'));        
          // logs 'false'
console.log(isPalindrome('A car, a man, a maraca'));
           // logs 'true'


11,、寫一個sum方法,當使用下面的語法調(diào)用時它將正常工作,。

console.log(sum(2,3));   
// Outputs 5
console.log(sum(2)(3));
 // Outputs 5

有(至少)兩種方法可以做到這一點:

METHOD 1

function sum(x) {  if (arguments.length == 2) {    
return arguments[0] + arguments[1];  } else {  
 return function(y) { return x + y; };  }}

在JavaScript中,,函數(shù)提供對參數(shù)對象的訪問,該對象提供對傳遞給函數(shù)的實際參數(shù)的訪問,。這使我們能夠使用length屬性在運行時確定傳遞給函數(shù)的參數(shù)的數(shù)量

如果傳遞兩個參數(shù),我們只需將它們相加并返回,。

否則,,我們假設它是以sum(2)(3)的形式被調(diào)用的,所以我們返回一個匿名函數(shù),,它將傳遞給sum()(在本例中為2)的參數(shù)和傳遞給匿名函數(shù)的參數(shù)這種情況3),。

METHOD 2

function sum(x, y) {  
if (y !== undefined) {
   return x + y;  } else {    
   return function(y) { return x + y; };  }}

當函數(shù)被調(diào)用時,JavaScript不需要參數(shù)的數(shù)量來匹配函數(shù)定義中參數(shù)的數(shù)量,。如果傳遞的參數(shù)數(shù)量超過了函數(shù)定義中參數(shù)的數(shù)量,,則超出的參數(shù)將被忽略。另一方面,,如果傳遞的參數(shù)數(shù)量少于函數(shù)定義中的參數(shù)數(shù)量,,則在函數(shù)內(nèi)引用時,缺少的參數(shù)將具有未定義的值,。因此,,在上面的例子中,通過簡單地檢查第二個參數(shù)是否未定義,,我們可以確定函數(shù)被調(diào)用的方式并相應地繼續(xù),。

12、考慮下面的代碼片段

for (var i = 0; i <>5; i++) {
 var btn = document.createElement('button');  btn.appendChild(document.createTextNode('Button ' + i));  btn.addEventListener('click', function(){ console.log(i); });
  document.body.appendChild(btn);}

(a) 當用戶點擊“按鈕4”時,,什么被記錄到控制臺,?為什么?

(b) 提供一個或多個可按預期工作的替代實現(xiàn),。

答:

(a) 無論用戶點擊哪個按鈕,,數(shù)字5將始終記錄到控制臺。這是因為,,在調(diào)用onclick方法(對于任何按鈕)時,,for循環(huán)已經(jīng)完成,,并且變量i已經(jīng)具有值5.(如果受訪者知道足夠的話就可以獲得獎勵點數(shù)關于執(zhí)行上下文,變量對象,,激活對象和內(nèi)部“范圍”屬性如何影響閉包行為,。)

(b) 使這項工作的關鍵是通過將它傳遞給新創(chuàng)建的函數(shù)對象來捕獲每次通過for循環(huán)的i的值。以下是四種可能的方法來實現(xiàn)這一點:

for (var i = 0; i < 5;="" i++)="">  var btn = document.createElement('button');  btn.appendChild(document.createTextNode('Button ' + i));  btn.addEventListener('click', (function(i) {    return function() { console.log(i); };  })(i));  document.body.appendChild(btn);}

或者,,您可以將新的匿名函數(shù)中的整個調(diào)用包裝為btn.addEventListener:

for (var i = 0; i < 5;="" i++)="">  var btn = document.createElement('button');  btn.appendChild(document.createTextNode('Button ' + i));  (function (i) {    btn.addEventListener('click', function() { console.log(i); });  })(i);  document.body.appendChild(btn);}

或者,,我們可以通過調(diào)用數(shù)組對象的原生forEach方法來替換for循環(huán):

['a', 'b', 'c', 'd', 'e'].forEach(function (value, i) { 
 var btn = document.createElement('button');  btn.appendChild(document.createTextNode('Button ' + i));  btn.addEventListener('click', function() { console.log(i); });
   document.body.appendChild(btn);});

最后,最簡單的解決方案,,如果你在ES6 / ES2015上下文中,,就是使用let i而不是var i:

for (let i = 0; i <>5; i++) {  
var btn = document.createElement('button');  btn.appendChild(document.createTextNode('Button ' + i));  btn.addEventListener('click', function(){ console.log(i); });
 document.body.appendChild(btn);}


13、假設d是范圍內(nèi)的“空”對象:

var d = {};

...使用下面的代碼完成了什么,?

[ 'zebra', 'horse' ].forEach(function(k) {    d[k] = undefined;});

上面顯示的代碼片段在對象d上設置了兩個屬性,。理想情況下,對具有未設置鍵的JavaScript對象執(zhí)行的查找評估為未定義,。但是運行這段代碼會將這些屬性標記為對象的“自己的屬性”,。

這是確保對象具有一組給定屬性的有用策略。將該對象傳遞給Object.keys將返回一個包含這些設置鍵的數(shù)組(即使它們的值未定義),。


14,、下面的代碼將輸出到控制臺,為什么,?

var arr1 = 'john'.split('');
var arr2 = arr1.reverse();
var arr3 = 'jones'.split('');arr2.push(arr3);console.log('array 1: length=' + arr1.length + ' last=' + arr1.slice(-1));console.log('array 2: length=' + arr2.length + ' last=' + arr2.slice(-1));

記錄的輸出將是:

'array 1: length=5 last=j,o,n,e,s''array 2: length=5 last=j,o,n,e,s'

arr1和arr2是相同的(即['n',,'h','o',,'j',,['j','o',,'n',,'e','s']])上述代碼由于以下原因而被執(zhí)行:

  • 調(diào)用數(shù)組對象的reverse()方法不僅以相反的順序返回數(shù)組,,它還顛倒了數(shù)組本身的順序(即在這種情況下,,arr1)。

  • reverse()方法返回對數(shù)組本身的引用(即,,在這種情況下為arr1),。因此,arr2僅僅是對arr1的引用(而不是副本),。因此,,當對arr2做任何事情時(即,當我們調(diào)用arr2.push(arr3);)時,,arr1也會受到影響,,因為arr1和arr2只是對同一個對象的引用,。

這里有幾個觀點可以讓人們回答這個問題:

  • 將數(shù)組傳遞給另一個數(shù)組的push()方法會將整個數(shù)組作為單個元素推入數(shù)組的末尾。結果,,聲明arr2.push(arr3);將arr3作為一個整體添加到arr2的末尾(即,,它不連接兩個數(shù)組,這就是concat()方法的用途),。

  • 像Python一樣,,JavaScript在調(diào)用像slice()這樣的數(shù)組方法時,會承認負面下標,,以此作為在數(shù)組末尾引用元素的方式;例如,,下標-1表示數(shù)組中的最后一個元素,依此類推,。


15,、下面的代碼將輸出到控制臺,為什么,?

console.log(1 +  '2' + '2');console.log(1 +  +'2' + '2');console.log(1 +  -'1' + '2');console.log(+'1' +  '1' + '2');console.log( 'A' - 'B' + '2');console.log( 'A' - 'B' + 2);

以上代碼將輸出到控制臺:

'122''32''02''112''NaN2'NaN

這是為什么...

這里的基本問題是JavaScript(ECMAScript)是一種松散類型的語言,,它對值執(zhí)行自動類型轉(zhuǎn)換以適應正在執(zhí)行的操作。讓我們來看看這是如何與上面的每個例子進行比較,。

示例1:1 +“2”+“2”輸出:“122”說明:第一個操作在1 +“2”中執(zhí)行。由于其中一個操作數(shù)(“2”)是一個字符串,,所以JavaScript假定需要執(zhí)行字符串連接,,因此將1的類型轉(zhuǎn)換為“1”,1 +“2”轉(zhuǎn)換為“12”,。然后,,“12”+“2”產(chǎn)生“122”。

示例2:1 + +“2”+“2”輸出:“32”說明:根據(jù)操作順序,,要執(zhí)行的第一個操作是+“2”(第一個“2”之前的額外+被視為一個一元運算符),。因此,JavaScript將“2”的類型轉(zhuǎn)換為數(shù)字,,然后將一元+符號應用于它(即將其視為正數(shù)),。結果,下一個操作現(xiàn)在是1 + 2,,當然這會產(chǎn)生3.但是,,我們有一個數(shù)字和一個字符串之間的操作(即3和“2”),所以JavaScript再次轉(zhuǎn)換數(shù)值賦給一個字符串并執(zhí)行字符串連接,,產(chǎn)生“32”,。

示例3:1 + - “1”+“2”輸出:“02”說明:這里的解釋與前面的示例相同,只是一元運算符是 - 而不是+,。因此,,“1”變?yōu)?,,然后在應用 - 時將其變?yōu)?1,然后將其加1到產(chǎn)生0,,然后轉(zhuǎn)換為字符串并與最終的“2”操作數(shù)連接,,產(chǎn)生“02”。

示例4:+“1”+“1”+“2”輸出:“112”說明:盡管第一個“1”操作數(shù)是基于其前面的一元+運算符的數(shù)值類型轉(zhuǎn)換的,,當它與第二個“1”操作數(shù)連接在一起時返回一個字符串,,然后與最終的“2”操作數(shù)連接,產(chǎn)生字符串“112”,。

示例5:“A” - “B”+“2”輸出:“NaN2”說明:由于 - 運算符不能應用于字符串,,并且既不能將“A”也不能將“B”轉(zhuǎn)換為數(shù)值, “ - ”B“產(chǎn)生NaN,,然后與字符串”2“串聯(lián)產(chǎn)生”NaN2“,。

例6:“A” - “B”+2輸出:NaN說明:在前面的例子中,“A” - “B”產(chǎn)生NaN,。但是任何運算符應用于NaN和其他數(shù)字操作數(shù)仍然會產(chǎn)生NaN,。

16、如果數(shù)組列表太大,,以下遞歸代碼將導致堆棧溢出,。你如何解決這個問題,仍然保留遞歸模式,?

var list = readHugeList();
var nextListItem = function() {    
var item = list.pop();    if (item) {      
 // process the list item...        nextListItem();    }};

通過修改nextListItem函數(shù)可以避免潛在的堆棧溢出,,如下所示:

var list = readHugeList();
var nextListItem = function() {  
 var item = list.pop();    if (item) {  
      // process the list item...        setTimeout( nextListItem, 0);    }};

堆棧溢出被消除,因為事件循環(huán)處理遞歸,,而不是調(diào)用堆棧,。當nextListItem運行時,如果item不為null,,則將超時函數(shù)(nextListItem)推送到事件隊列,,并且函數(shù)退出,從而使調(diào)用堆棧清零,。當事件隊列運行超時事件時,,將處理下一個項目,并設置一個計時器以再次調(diào)用nextListItem,。因此,,該方法從頭到尾不經(jīng)過直接遞歸調(diào)用即可處理,因此調(diào)用堆棧保持清晰,,無論迭代次數(shù)如何,。


17、什么是JavaScript中的“閉包”?舉一個例子,。

閉包是一個內(nèi)部函數(shù),,它可以訪問外部(封閉)函數(shù)的作用域鏈中的變量。閉包可以訪問三個范圍內(nèi)的變量;具體來說:(1)變量在其自己的范圍內(nèi),,(2)封閉函數(shù)范圍內(nèi)的變量,,以及(3)全局變量。

這里是一個例子:

var globalVar = 'xyz';
(function outerFunc(outerArg) {    var outerVar = 'a';    (function innerFunc(innerArg) {    var innerVar = 'b';    console.log(        
'outerArg = ' + outerArg + '\n' +  
     'innerArg = ' + innerArg + '\n' +  
          'outerVar = ' + outerVar + '\n' +    
              'innerVar = ' + innerVar + '\n' +    
                 'globalVar = ' + globalVar);    })(456);})(123);

在上面的例子中,,innerFunc,,outerFunc和全局名稱空間的變量都在innerFunc的范圍內(nèi)。上面的代碼將產(chǎn)生以下輸出:

outerArg = 123innerArg = 456outerVar = ainnerVar = bglobalVar = xyz


18,、以下代碼的輸出是什么:

for (var i = 0; i <>5; i++) {    setTimeout(function() { 
console.log(i); }, i * 1000 );}

解釋你的答案,。如何在這里使用閉包?

顯示的代碼示例不會顯示值0,1,2,3和4,,這可能是預期的;而是顯示5,5,5,5,。

這是因為循環(huán)內(nèi)執(zhí)行的每個函數(shù)將在整個循環(huán)完成后執(zhí)行,因此所有函數(shù)都會引用存儲在i中的最后一個值,,即5,。

通過為每次迭代創(chuàng)建一個唯一的作用域 ,可以使用閉包來防止這個問題,,并將該變量的每個唯一值存儲在其作用域中,,如下所示:

for (var i = 0; i < 5;="" i++)="">    (function(x) {        setTimeout(function()
{ console.log(x); }, x * 1000 );    })(i);}

這會產(chǎn)生將0,1,2,3和4記錄到控制臺的可能結果。

在ES2015上下文中,,您可以在原始代碼中簡單地使用let而不是var:

for (let i = 0; i <>5; i++) {    setTimeout(function() {
console.log(i); }, i * 1000 );}

19,、以下幾行代碼輸出到控制臺?

console.log('0 || 1 = '+(0 || 1));
console.log('1 || 2 = '+(1 || 2));
console.log('0 && 1 = '+(0 && 1));
console.log('1 && 2 = '+(1 && 2));

解釋你的答案,。

該代碼將輸出以下四行:

0 || 1 = 11 || 2 = 10 && 1 = 01 && 2 = 2

在JavaScript中,,都是||和&&是邏輯運算符,,當從左向右計算時返回第一個完全確定的“邏輯值”,。

或(||)運算符。在形式為X || Y的表達式中,,首先計算X并將其解釋為布爾值,。如果此布爾值為真,則返回true(1),,并且不計算Y,,因為“或”條件已經(jīng)滿足。但是,,如果此布爾值為“假”,,我們?nèi)匀徊恢繶 || Y是真還是假,直到我們評估Y,并將其解釋為布爾值,。

因此,,0 || 1評估為真(1),正如1 || 2,。

和(&&)運算符,。在X && Y形式的表達式中,首先評估X并將其解釋為布爾值,。如果此布爾值為false,,則返回false(0)并且不評估Y,因為“and”條件已失敗,。但是,,如果這個布爾值為“真”,我們?nèi)匀徊恢繶 && Y是真還是假,,直到我們評估Y,,并將其解釋為布爾值。

然而,,&&運算符的有趣之處在于,,當表達式評估為“真”時,則返回表達式本身,。這很好,,因為它在邏輯表達式中被視為“真”,但也可以用于在您關心時返回該值,。這解釋了為什么,,有點令人驚訝的是,1 && 2返回2(而你可能會期望它返回true或1),。


20 ,、下面的代碼執(zhí)行時輸出是什么?說明,。

console.log(false == '0')console.log(false === '0')

該代碼將輸出:

truefalse

在JavaScript中,,有兩套相等運算符。三重相等運算符===的行為與任何傳統(tǒng)的相等運算符相同:如果兩側的兩個表達式具有相同的類型和相同的值,,則計算結果為true,。然而,雙等號運算符在比較它們之前試圖強制這些值,。因此,,通常使用===而不是==。對于,!== vs,!=也是如此。


21、以下代碼的輸出是什么,?解釋你的答案,。

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

此代碼的輸出將是456(不是123)。

原因如下:設置對象屬性時,,JavaScript會隱式地將參數(shù)值串聯(lián)起來,。在這種情況下,由于b和c都是對象,,它們都將被轉(zhuǎn)換為“[object Object]”,。因此,a [b]和a [c]都等價于[“[object Object]”],,并且可以互換使用,。因此,設置或引用[c]與設置或引用[b]完全相同,。


22,、以下代碼將輸出到控制臺中.

console.log((function f(n){return ((n > 1) ? n * f(n-1) : n)})(10));

該代碼將輸出10階乘的值(即10!或3,628,800),。

原因如下:

命名函數(shù)f()以遞歸方式調(diào)用自身,,直到它調(diào)用f(1),它簡單地返回1.因此,,這就是它的作用:

f(1): returns n, which is 1f(2): returns 2 * f(1), which is 2f(3): returns 3 * f(2), which is 6f(4): returns 4 * f(3), which is 24f(5): returns 5 * f(4), which is 120f(6): returns 6 * f(5), which is 720f(7): returns 7 * f(6), which is 5040f(8): returns 8 * f(7), which is 40320f(9): returns 9 * f(8), which is 362880f(10): returns 10 * f(9), which is 3628800


23 ,、考慮下面的代碼片段??刂婆_的輸出是什么,,為什么?

(function(x) {    return (function(y) {        console.log(x);    })(2)})(1);

輸出將為1,,即使x的值從未在內(nèi)部函數(shù)中設置,。原因如下:

正如我們的JavaScript招聘指南中所解釋的,閉包是一個函數(shù),,以及創(chuàng)建閉包時在范圍內(nèi)的所有變量或函數(shù),。在JavaScript中,閉包被實現(xiàn)為“內(nèi)部函數(shù)”;即在另一功能的主體內(nèi)定義的功能,。閉包的一個重要特征是內(nèi)部函數(shù)仍然可以訪問外部函數(shù)的變量,。

因此,,在這個例子中,,因為x沒有在內(nèi)部函數(shù)中定義,所以在外部函數(shù)的作用域中搜索一個定義的變量x,,該變量的值為1,。


24、以下代碼將輸出到控制臺以及為什么

var hero = {    
_name: 'John Doe',    getSecretIdentity: function (){      
 return this._name;    }};
 var stoleSecretIdentity = hero.getSecretIdentity;
 console.log(stoleSecretIdentity());
console
.log(hero.getSecretIdentity());

這段代碼有什么問題,以及如何解決這個問題,。

該代碼將輸出:

undefinedJohn Doe

第一個console.log打印未定義,,因為我們從hero對象中提取方法,所以stoleSecretIdentity()在_name屬性不存在的全局上下文(即窗口對象)中被調(diào)用,。

修復stoleSecretIdentity()函數(shù)的一種方法如下:

var stoleSecretIdentity = hero.getSecretIdentity.bind(hero);


25,、創(chuàng)建一個函數(shù),給定頁面上的DOM元素,,將訪問元素本身及其所有后代(不僅僅是它的直接子元素),。對于每個訪問的元素,函數(shù)應該將該元素傳遞給提供的回調(diào)函數(shù),。

該函數(shù)的參數(shù)應該是:

  • 一個 DOM 元素

  • 一個回調(diào)函數(shù)(以DOM元素作為參數(shù))

訪問樹中的所有元素(DOM)是[經(jīng)典的深度優(yōu)先搜索算法]Depth-First-Search algorithm應用程序,。以下是一個示例解決方案:

function Traverse(p_element,p_callback) {   p_callback(p_element);   
var list = p_element.children;  
for (var i = 0; i <>list.length; i++) {       Traverse(list[i],p_callback);  
// recursive call   }}


27、在JavaScript中測試您的這些知識:以下代碼的輸出是什么,?

var length = 10;function fn() {  
 console.log(this.length);}var obj = {
  length: 5,  method: function(fn) {    fn();    arguments[0]();  }};obj.method(fn, 1);

輸出:

102

為什么不是10和5,?

首先,由于fn作為函數(shù)方法的參數(shù)傳遞,,函數(shù)fn的作用域(this)是窗口,。 var length = 10;在窗口級別聲明。它也可以作為window.length或length或this.length來訪問(當這個===窗口時),。

方法綁定到Object obj,,obj.method用參數(shù)fn和1調(diào)用。雖然方法只接受一個參數(shù),,但調(diào)用它時已經(jīng)傳遞了兩個參數(shù);第一個是函數(shù)回調(diào),,其他只是一個數(shù)字。

當在內(nèi)部方法中調(diào)用fn()時,,該函數(shù)在全局級別作為參數(shù)傳遞,,this.length將有權訪問在Object obj中定義的var length = 10(全局聲明)而不是length = 5。

現(xiàn)在,,我們知道我們可以使用arguments []數(shù)組訪問JavaScript函數(shù)中的任意數(shù)量的參數(shù),。

因此arguments0只不過是調(diào)用fn()。在fn里面,,這個函數(shù)的作用域成為參數(shù)數(shù)組,,并且記錄參數(shù)[]的長度將返回2。

因此輸出將如上所述,。


28,、考慮下面的代碼。輸出是什么,,為什么,?

(function () {    try {        throw new Error();    } catch (x) {        var x = 1, y = 2;        console.log(x);    }    console.log(x);    console.log(y);})();
1undefined2

var語句被掛起(沒有它們的值初始化)到它所屬的全局或函數(shù)作用域的頂部,,即使它位于with或catch塊內(nèi)。但是,,錯誤的標識符只在catch塊內(nèi)部可見,。它相當于:

(function () {    var x, y; // outer and hoisted    try {        throw new Error();    } catch (x /* inner */) {        x = 1; // inner x, not the outer one        y = 2; // there is only one y, which is in the outer scope        console.log(x /* inner */);    }    console.log(x);    console.log(y);})();


29、這段代碼的輸出是什么,?

var x = 21;
var girl = function () {    
console.log(x);  
 var x = 20;};girl ();

21,,也不是20,結果是‘undefined’的

這是因為JavaScript初始化沒有被掛起,。

(為什么它不顯示21的全局值,?原因是當函數(shù)執(zhí)行時,它檢查是否存在本地x變量但尚未聲明它,,因此它不會查找全局變量,。 )


30、你如何克隆一個對象,?

var obj = {a: 1 ,b: 2}var objclone = Object.assign({},obj);

現(xiàn)在objclone的值是{a:1,,b:2},但指向與obj不同的對象,。

但請注意潛在的缺陷:Object.clone()只會執(zhí)行淺拷貝,,而不是深拷貝。這意味著嵌套的對象不會被復制,。他們?nèi)匀灰门c原始相同的嵌套對象:

let obj = {    
a: 1,    b: 2,    c: {  
     age: 30    }};
     var objclone = Object.assign({},obj);
     console.log('objclone: ', objclone);
obj.c.age = 45;console.log('After Change - obj: ', obj);    
        // 45 - This also changes
console.log('After Change - objclone: ', objclone);
         // 45
for (let i = 0; i <>5; i++) {  setTimeout(function() {
console.log(i); }, i * 1000 );}


31,、此代碼將打印什么?

for (let i = 0; i <>5; i++) {    setTimeout(function() { 
console.log(i); }, i * 1000 );}

它會打印0 1 2 3 4,,因為我們在這里使用let而不是var,。變量i只能在for循環(huán)的塊范圍中看到。


32,、以下幾行輸出什么,,為什么?

console.log(1 <>2 <>3);console.log(3 > 2 > 1);

第一條語句返回true,,如預期的那樣,。

第二個返回false是因為引擎如何針對<和>的操作符關聯(lián)性工作。它比較從左到右,,所以3> 2> 1 JavaScript翻譯為true> 1. true具有值1,,因此它比較1> 1,這是錯誤的,。


33,、如何在數(shù)組的開頭添加元素?最后如何添加一個,?

var myArray = ['a', 'b', 'c', 'd'];myArray.push('end');myArray.unshift('start');console.log(myArray); 
// ['start', 'a', 'b', 'c', 'd', 'end']

使用ES6,,可以使用擴展運算符:

myArray = ['start', ...myArray];myArray = [...myArray, 'end'];

或者,簡而言之:

myArray = ['start', ...myArray, 'end'];


34,、想象一下你有這樣的代碼:

var a = [1, 2, 3];

a)這會導致崩潰嗎,?

a[10] = 99;

b)這個輸出是什么?

console.log(a[6]);

a)它不會崩潰,。 JavaScript引擎將使陣列插槽3至9成為“空插槽”,。

b)在這里,a [6]將輸出未定義的值,,但時隙仍為空,,而不是未定義的。在某些情況下,,這可能是一個重要的細微差別,。例如,使用map()時,,map()的輸出中的空插槽將保持為空,,但未定義的插槽將使用傳遞給它的函數(shù)重映射:

var b = [undefined];b[2] = 1;console.log(b);           
  // (3) [undefined, empty × 1, 1]
console.log(b.map(e => 7));
   // (3) [7,         empty × 1, 7]


35、typeof undefined == typeof NULL的值是什么,?

該表達式將被評估為true,,因為NULL將被視為任何其他未定義的變量。

注意:JavaScript區(qū)分大小寫,,我們在這里使用NULL而不是null,。


36、代碼返回后會怎么樣,?

console.log(typeof typeof 1);

string

typeof 1將返回“number”,,typeof“number”將返回字符串。


37,、以下代碼輸出什么,?為什么?

var b = 1;function outer(){   
    var b = 2    function inner(){        b++;    
       var b = 3;    
          console.log(b)    }    inner();}outer();

輸出到控制臺將是“3”,。

在這個例子中有三個閉包,,每個都有它自己的var b聲明。當調(diào)用變量時,,將按照從本地到全局的順序檢查閉包,,直到找到實例。由于內(nèi)部閉包有自己的b變量,,這就是輸出,。

此外,由于提升內(nèi)部的代碼將被解釋如下:

function inner () {    
var b;
// b is undefined    b++;
// b is NaN    b = 3;
// b is 3    console.log(b);
 // output '3'}

面試比棘手的技術問題要多,,所以這些僅僅是作為指導,。并不是每個值得聘用的“A”候選人都能夠回答所有問題,,也不會回答他們都保證有“A”候選人。在這一天結束時,,招聘仍然是一門藝術,,一門科學 - 還有很多工作。.

    本站是提供個人知識管理的網(wǎng)絡存儲空間,,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式,、誘導購買等信息,,謹防詐騙。如發(fā)現(xiàn)有害或侵權內(nèi)容,,請點擊一鍵舉報,。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多