【轉載】十三道JavaScript基礎題,你是否都作對了?

這是我在Javascript微信公衆號上看到的一篇文章,以爲挺有意思的,因此轉載過來跟你們分享一下,同時,對這些題目也加上了一些我我的的理解,若是有不對的地方,請你們指正。面試


題目一數組

(function(){
   return typeof arguments;
})();

答案:Object瀏覽器

typeof所返回的可能值爲:numberstringbooleanundefinedobjectfunction。而咱們知道arguments是一個僞數組,而僞數組也是一個對象,因此答案應該是Object。那麼,若是把typeof arguments改爲arguments instanceof Array呢?微信

clipboard.png

能夠看到,返回的是false。所以,僞數組不是一個數組,只有在使用了Array.prototype.slice.call()進行了轉換後,才能轉化成一個真數組。函數


題目二this

var f = function g(){ return 23; };
typeof g();

答案:會報錯(g()未定義)spa

這段代碼中混合了函數聲明和函數表達式的形式,而函數其實是綁定到了f上而不是g。可是這麼寫是否符合Javascript的要求呢?在《Javascript高級程序設計》中:prototype

也能夠同時使用函數聲明和函數表達式,例如:var sum = function sum(){}。不過,這種語法在safari中會致使錯誤。設計

既然在除了safari之外的瀏覽器能夠同時使用函數聲明和函數表達式來聲明函數,那麼爲何題目中的代碼會報錯呢?個人理解是,這樣寫的結果是致使了函數名g被包裝進了f中,變成了f的一個局部變量,只能在f函數內部訪問到g,我把代碼修改了一下:code

var f = function g(){ 
            alert(g);
            return 23; 
        };
f();

我在f函數內部訪問g,彈框彈出的內容爲function g(){ alert(g);return 23; },沒有報錯而且訪問成功,g的函數體內容與f是同樣的,只是函數名不同。

————————我是一條分割線——————————

咱們再來回顧一下函數聲明與函數表達式吧(由於在以前的一次面試中被問到了它們的區別,我一下沒打上來……因此仍是加強一下記憶)

函數聲明的形式:

function funcName(){ /*some code*/}

函數表達式的形式:

var funcName = function(){/*some code*/}

在《Javascript高級程序設計》中有一段話:

解析器在向執行環境中加載數據時,對函數聲明和函數表達式並不是一視同仁的。解析器會率先讀取函數聲明,並使其在執行任何代碼以前可用(能夠訪問);至於函數表達式,則必須等到解析器執行到它所在的代碼行,纔會真正被解釋執行。

也就是說,在函數聲明的代碼段以前訪問函數,是可以訪問到的(函數聲明提高)。而在函數表達式的代碼段以前訪問函數,則會發生錯誤,由於在執行到函數所在語句以前,函數表達式聲明的變量名中不會保存對函數的的引用。
除此以外函數聲明與函數表達式的語法實際上是等價的。


題目三:

(function(x){
  delete x;
  return x;
})(1);

答案:1

注意:delete是用來刪除對象的屬性,沒法刪除普通變量。


題目四

var y = 1, x = y = typeof x;
x;

答案:undefined
由於賦值運算是從右往左的,所以題目中的代碼展開來等價於:

var y = 1;
y = typeof x;
var x = y;
x;

第二行代碼在訪問x時,x並無聲明,值爲undefined,因此typeof x也就是undefined了。


題目五

(function f(f){
  return typeof f();
})(function(){ return 1; });

答案:number

把代碼分開來看會比較清楚:

var baz = function(){ return 1; };
(function f(f){
  return typeof f();
})(baz);

先將function(){ return 1; }賦值給baz,則baz()應該是1。再把baz當成參數傳入到當即執行函數中,當即執行函數返回的是傳入的參數的類型,即baz()的類型,baz()返回1類型爲number


題目六

var foo = {
  bar: function() { return this.baz; },
  baz: 1
};
 
(function(){
  return typeof arguments[0]();
})(foo.bar);

答案:undefined
這裏關鍵要理解this的所指。arguments[0]foo.bar,而函數中的this指的就是調用arguments[0]()這個函數的對象,即window對象。可是window對象並無baz這個屬性,所以,返回的是undefined


題目七

var foo = {
   bar: function(){ return this.baz; },
   baz: 1
} 
typeof (f = foo.bar)();

答案:undefined
將代碼改寫一些變成:

var foo = {
   bar: function(){ return this.baz; },
   baz: 1
} 
var f = foo.bar;
typeof f();

foo.bar是一個函數,將foo.bar賦值給了f,那麼f變成了一個函數名。直接調用f()時,調用它的對象爲window,而window中並無baz屬性,因此輸出的是undefined


題目八

var f = (function f(){ 
            return "1";
         }, function g(){ 
              return 2; 
         })();
typeof f;

答案:number
在這裏,咱們須要瞭解一下逗號操做符的做用:

在用於賦值時,逗號操做符總會返回表達式中的最後一項。

因此,這個當即執行函數返回的應該是後面那個函數的返回值,返回值爲2,類型爲number


題目九

var x = 1;
if (function f(){}) {
  x += typeof f;
}
x;

答案:1undefined
首先,第一個問題是:函數在判斷語句中判斷的結果是true仍是false?,咱們能夠運行一下如下代碼:

Boolean(function f(){});//true

將一個空函數轉換爲布爾型,結果爲true,因此題中的代碼是可以進入if語句的。那麼第二個問題是:爲何typeof f會是undefined?由於if判斷條件中並不能真正的聲明一個函數,所以,f是一個沒有被聲明過的函數名,它的類型爲undefined


題目十

(function f(){
  function f(){ return 1; }
  return f();
  function f(){ return 2; }
})();

答案:2
咱們在題目四里說過:Javascript解析器會率先讀取函數聲明,使它在任何代碼之間可用。所以,在外層函數f函數體內的兩個函數聲明,都會提高到return f()以前執行。而又由於Javascript沒有重載,所以以最後執行的同名函數輸出結果爲準。


題目十一

function f(){ return f; }
new f() instanceof f;

答案:false
一、首先咱們要了解instanceof的做用:instanceof是用來檢測變量是不是給定引用類型的實例。
二、而後再看f()函數體中return f,返回了本身。
三、經過new來調用構造函數生成實例的過程爲:1)建立一個空對象;2)將類的prototype中的屬性和方法複製到實例中;3)將第一步建立的空對象作爲類的參數調用類的構造函數;4)返回一個新的實例對象。
然而,在以new形式調用構造函數f()時,f()返回了自身,將new返回的實例對象覆蓋掉了,所以,new以後的結果不是f的一個引用了。


題目十二

var x = [typeof x, typeof y][1];
typeof typeof x;

答案:string
很明顯的能夠看出typeof x = undefinedtypeof y = undefined,那麼xundefined。其實其餘的都不看,光看typeof typeof就能肯定輸出的是string了。


題目十三

(function(foo){
  return typeof foo.bar;
})({ foo: { bar: 1 } });

答案:undefined
這道題目有一個小陷阱,一不注意還真被忽悠進去了。咱們仔細看一個參數傳入的內容最外面有一對{},那麼咱們把題目修改一下就一目瞭然了:

var temp = { foo: { bar: 1 } };
(function(foo){
  return typeof foo.bar;
})(temp);

傳入的參數爲temp這個對象,所以函數中的foo.bar實際上爲temp.bar,可是temp裏只有foo一個屬性,沒有bar,因此應該是undefined

相關文章
相關標籤/搜索