成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

幾道javascript練習(xí)題

qylost / 1861人閱讀

摘要:另一個(gè)重復(fù)輸出一個(gè)給定的字符串第一個(gè)參數(shù)次第二個(gè)參數(shù),如果第二個(gè)參數(shù)不是正數(shù)的時(shí)候,返回空字符串。這里是解決方案步驟檢查是否為負(fù)數(shù),如果為則返回一個(gè)空字符串步驟檢查是否等于,如果是,返回字符串本身。

走在前端的大道上

問題1: 作用域(Scope)

考慮以下代碼:

(function() {
   var a = b = 5;
})();
 
console.log(b);

控制臺(tái)(console)會(huì)打印出什么?

答案

上述代碼會(huì)打印出5。

這個(gè)問題的陷阱就是,在立即執(zhí)行函數(shù)表達(dá)式(IIFE)中,有兩個(gè)賦值,但是其中變量a使用關(guān)鍵詞var來(lái)聲明。這就意味著a是這個(gè)函數(shù)的局部變量。與此相反,b被分配給了全局作用域(譯注:也就是全局變量)。

這個(gè)問題另一個(gè)陷阱就是,在函數(shù)中沒有使用”嚴(yán)格模式” ("use strict";)。如果 嚴(yán)格模式開啟,那么代碼就會(huì)報(bào)錯(cuò) ” Uncaught ReferenceError: b is not defined” 。請(qǐng)記住,如果這是預(yù)期的行為,嚴(yán)格模式要求你顯式地引用全局作用域。所以,你需要像下面這么寫:

(function() {
   "use strict";
   var a = window.b = 5;
})();
 
console.log(b);
問題2: 創(chuàng)建 “原生(native)” 方法

在 String 對(duì)象上定義一個(gè) repeatify 函數(shù)。這個(gè)函數(shù)接受一個(gè)整數(shù)參數(shù),來(lái)明確字符串需要重復(fù)幾次。這個(gè)函數(shù)要求字符串重復(fù)指定的次數(shù)。舉個(gè)例子:

console.log("hello".repeatify(3));

應(yīng)該打印出hellohellohello.

答案

一個(gè)可行的做法如下:

String.prototype.repeatify = String.prototype.repeatify || function(times) {
   var str = "";
 
   for (var i = 0; i < times; i++) {
      str += this;
   }
 
   return str;
};

這個(gè)問題測(cè)試了開發(fā)人員對(duì) javascript 中繼承及原型(prototype)屬性的知識(shí)。這也驗(yàn)證了開發(fā)人員是否有能力擴(kuò)展原生數(shù)據(jù)類型功能(雖然不應(yīng)該這么做)。

在這里,另一個(gè)關(guān)鍵點(diǎn)是,看你怎樣避免重寫可能已經(jīng)定義了的方法。這可以通過(guò)在定義自己的方法之前,檢測(cè)方法是否已經(jīng)存在。

String.prototype.repeatify = String.prototype.repeatify || function(times) {/* code here */}; 

當(dāng)你被問起去擴(kuò)展一個(gè)Javascript方法時(shí),這個(gè)技術(shù)非常有用。

另一個(gè):重復(fù)輸出一個(gè)給定的字符串(str第一個(gè)參數(shù))n 次 (num第二個(gè)參數(shù)),如果第二個(gè)參數(shù)num不是正數(shù)的時(shí)候,返回空字符串。

function repeatStringNumTimes(str, num) {
  return str;
}
repeatStringNumTimes("abc", 3);

提供測(cè)試情況:

repeatStringNumTimes("*", 3) //應(yīng)該返回 "***".
repeatStringNumTimes("abc", 3) //應(yīng)該返回 "abcabcabc".
repeatStringNumTimes("abc", 4) //應(yīng)該返回 "abcabcabcabc".
repeatStringNumTimes("abc", 1) //應(yīng)該返回 "abc".
repeatStringNumTimes("*", 8) //應(yīng)該返回 "********".
repeatStringNumTimes("abc", -2) //應(yīng)該返回 "".

解題思路:

三種方法:

使用 while 循環(huán)
使用遞歸
使用ES6 repeat()
方法1:通過(guò) while 循環(huán)重復(fù)輸出一個(gè)字符串

這可能是最常規(guī)的解題思路。while 語(yǔ)句只要指定的條件計(jì)算結(jié)果為true的時(shí)候,就執(zhí)行其語(yǔ)句。while 語(yǔ)句結(jié)構(gòu)大概是這樣的:

while (condition)
  statement

在每次通過(guò)循環(huán)之前計(jì)算條件結(jié)果。如果條件為true,則執(zhí)行語(yǔ)句。如果條件為false,則執(zhí)行繼續(xù) while 循環(huán)之后的任何語(yǔ)句。

只要條件為true,語(yǔ)句就會(huì)執(zhí)行。 這里是解決方案:

function repeatStringNumTimes(string, times) {
  // 第1步. 常見一個(gè)空字符,用來(lái)寄存重復(fù)的字符串
  var repeatedString = "";
 
  // 第2步. 設(shè)置 while 循環(huán)的條件為(times > 0) 作為檢查
  while (times > 0) { // 只要 times 大于 0, 語(yǔ)句就會(huì)執(zhí)行
    // 執(zhí)行語(yǔ)句 statement
    repeatedString += string; // 等價(jià)于 repeatedString = repeatedString + string; 
    times--; // 遞減,等價(jià)于 times = times - 1; 
  }
  /* while循環(huán)邏輯
          條件        T/F    repeatedString += string   結(jié)果          次數(shù)
    1th   (3 > 0)    true    "" + "abc"                "abc"          2
    2th   (2 > 0)    true    "abc" + "abc"             "abcabc"       1
    3th   (1 > 0)    true    "abcabc" + "abc"          "abcabcabc"    0
    4th   (0 > 0)    false
    }
  */
  
  // 第3步. 返回重復(fù)字符串
  return repeatedString; // "abcabcabc"
}
 
repeatStringNumTimes("abc", 3);

去掉注釋后:

function repeatStringNumTimes(string, times) {
  var repeatedString = "";
  while (times > 0) {
    repeatedString += string;
    times--;
  }
  return repeatedString;
}
repeatStringNumTimes("abc", 3);

好,輕松完成!不過(guò)這里還可以有幾個(gè)變種:

對(duì)于老前端來(lái)說(shuō),首先一個(gè)可能會(huì)將字符串拼接,修改為 數(shù)組join()拼接字符串,例如:

function repeatStringNumTimes(string, times) {
  var repeatedArr = []; //
  while (times > 0) {
    repeatedArr.push(string);
    times--;
  }
  return repeatedArr.join("");
}
repeatStringNumTimes("abc", 3)

很多老前端都有用數(shù)組join()拼接字符串的“情懷”,因?yàn)楹茉缫郧捌毡檎J(rèn)為數(shù)組join()拼接字符串比字符串+拼接速度要快得多。不過(guò)現(xiàn)在未必,例如,V8 下+拼接字符串,要比數(shù)組join()拼接字符串快。我用這兩個(gè)方法測(cè)試了3萬(wàn)次重復(fù)輸出,只相差了幾毫秒。

另一個(gè)變種可以用 for 循環(huán):

function repeatStringNumTimes(string, times) {
  var repeatedString = "";
  for(var i = 0; i < times ;i++) {
    repeatedString += string;
  }
  return repeatedString;
}
repeatStringNumTimes("abc", 3)
方法2:通過(guò)條件判斷和遞歸重復(fù)輸出一個(gè)字符串

遞歸是一種通過(guò)重復(fù)地調(diào)用函數(shù)本身,直到它達(dá)到達(dá)結(jié)果為止的迭代操作的技術(shù)。為了使其正常工作,必須包括遞歸的一些關(guān)鍵特征。

第一種是基本情況:一個(gè)語(yǔ)句,通常在一個(gè)條件語(yǔ)句(如if)中,停止遞歸。

第二種是遞歸情況:調(diào)用遞歸函數(shù)本身的語(yǔ)句。

這里是解決方案:

function repeatStringNumTimes(string, times) {
  // 步驟1.檢查 times 是否為負(fù)數(shù),如果為 true 則返回一個(gè)空字符串 
  if (times < 0) {
    return "";
  }
  
  // 步驟2.檢查times是否等于1,如果是,返回字符串本身。
  if (times === 1) {
    return string;
  }
  
  // 步驟3. 使用遞歸
  else {
    return string + repeatStringNumTimes(string, times - 1); // return "abcabcabc";
  }
  /* 
    遞歸方法的第一部分你需要記住,你不會(huì)只調(diào)用一次,您將有好幾個(gè)嵌套調(diào)用
                 times       string + repeatStringNumTimes(string, times - 1)
      1st call   3           "abc" + ("abc", 3 - 1)
      2nd call   2           "abc" + ("abc", 2 - 1)
      3rd call   1           "abc" => if (times === 1) return string;
      4th call   0           ""   => if (times <= 0) return "";
    遞歸方法的第二部分
      4th call will return      ""
      3rd call will return     "abc"
      2nd call will return     "abc"
      1st call will return     "abc"
    最后調(diào)用是串聯(lián)所有字符串
    return "abc" + "abc" + "abc"; // return "abcabcabc";
  */
}
repeatStringNumTimes("abc", 3);

去掉注釋后:

function repeatStringNumTimes(string, times) {
  if(times < 0) 
    return "";
  if(times === 1) 
    return string;
  else 
    return string + repeatStringNumTimes(string, times - 1);
}
repeatStringNumTimes("abc", 3);
方法3:使用ES6 repeat() 方法重復(fù)輸出一個(gè)字符串

這個(gè)解決方案比較新潮,您將使用 String.prototype.repeat() 方法:

repeat() 方法構(gòu)造并返回一個(gè)新字符串,該字符串包含被連接在一起的指定數(shù)量的字符串的副本。 這個(gè)方法有一個(gè)參數(shù) count 表示重復(fù)次數(shù),介于0和正無(wú)窮大之間的整數(shù) : [0, +∞) 。表示在新構(gòu)造的字符串中重復(fù)了多少遍原字符串。重復(fù)次數(shù)不能為負(fù)數(shù)。重復(fù)次數(shù)必須小于 infinity,且長(zhǎng)度不會(huì)大于最長(zhǎng)的字符串。

這里是解決方案:

function repeatStringNumTimes(string, times) {
  //步驟1.如果 times 為正數(shù),返回重復(fù)的字符串
  if (times > 0) { // (3 > 0) => true
    return string.repeat(times); // return "abc".repeat(3); => return "abcabcabc";
  }
  
  //Step 2. Else 如果times是負(fù)數(shù),如果為true則返回一個(gè)空字符串
  else {
    return "";
  }
}
 
repeatStringNumTimes("abc", 3);

去掉注釋后:

function repeatStringNumTimes(string, times) {
  if (times > 0)
    return string.repeat(times);
  else
    return "";
}
repeatStringNumTimes("abc", 3);

您可以使用三元表達(dá)式作為 if/else 語(yǔ)句的快捷方式,如下所示:

function repeatStringNumTimes(string, times) {
  return times > 0 ? string.repeat(times) : "";
}
repeatStringNumTimes("abc", 3);
問題3: 變量提升(Hoisting)

執(zhí)行以下代碼的結(jié)果是什么?為什么?

function test() {
   console.log(a);
   console.log(foo());
   
   var a = 1;
   function foo() {
      return 2;
   }
}
 
test();

答案

這段代碼的執(zhí)行結(jié)果是undefined 和 2。

這個(gè)結(jié)果的原因是,變量和函數(shù)都被提升(hoisted) 到了函數(shù)體的頂部。因此,當(dāng)打印變量a時(shí),它雖存在于函數(shù)體(因?yàn)閍已經(jīng)被聲明),但仍然是undefined。換言之,上面的代碼等同于下面的代碼:

function test() {
   var a;
   function foo() {
      return 2;
   }
 
   console.log(a);
   console.log(foo());
   
   a = 1;
}
 
test();
問題4: 在javascript中,this是如何工作的

以下代碼的結(jié)果是什么?請(qǐng)解釋你的答案。

var fullname = "John Doe";
var obj = {
   fullname: "Colin Ihrig",
   prop: {
      fullname: "Aurelio De Rosa",
      getFullname: function() {
         return this.fullname;
      }
   }
};
 
console.log(obj.prop.getFullname());
 
var test = obj.prop.getFullname;
 
console.log(test());

答案

這段代碼打印結(jié)果是:Aurelio De Rosa 和 John Doe 。原因是,JavaScript中關(guān)鍵字this所引用的是函數(shù)上下文,取決于函數(shù)是如何調(diào)用的,而不是怎么被定義的。

在第一個(gè)console.log(),getFullname()是作為obj.prop對(duì)象的函數(shù)被調(diào)用。因此,當(dāng)前的上下文指代后者,并且函數(shù)返回這個(gè)對(duì)象的fullname屬性。相反,當(dāng)getFullname()被賦值給test變量時(shí),當(dāng)前的上下文是全局對(duì)象window,這是因?yàn)閠est被隱式地作為全局對(duì)象的屬性。基于這一點(diǎn),函數(shù)返回window的fullname,在本例中即為第一行代碼設(shè)置的。

問題5: call() 和 apply()

修復(fù)前一個(gè)問題,讓最后一個(gè)console.log() 打印輸出Aurelio De Rosa.

答案

這個(gè)問題可以通過(guò)運(yùn)用call()或者apply()方法強(qiáng)制轉(zhuǎn)換上下文環(huán)境。如果你不了解這兩個(gè)方法及它們的區(qū)別,我建議你看看這篇文章 function.call和function.apply之間有和區(qū)別?。 下面的代碼中,我用了call(),但apply()也能產(chǎn)生同樣的結(jié)果:

console.log(test.call(obj.prop));

問題6: 閉包(Closures)

考慮下面的代碼:

var nodes = document.getElementsByTagName("button");
for (var i = 0; i < nodes.length; i++) {
   nodes[i].addEventListener("click", function() {
      console.log("You clicked element #" + i);
   });
}

請(qǐng)問,如果用戶點(diǎn)擊第一個(gè)和第四個(gè)按鈕的時(shí)候,控制臺(tái)分別打印的結(jié)果是什么?為什么?

答案

上面的代碼考察了一個(gè)非常重要的 JavaScript 概念:閉包(Closures)。對(duì)于每一個(gè)JavaScript開發(fā)者來(lái)說(shuō),如果你想在網(wǎng)頁(yè)中編寫5行以上的代碼,那么準(zhǔn)確理解和恰當(dāng)使用閉包是非常重要的。如果你想開始學(xué)習(xí)或者只是想簡(jiǎn)單地溫習(xí)一下閉包,那么我強(qiáng)烈建議你去閱讀 Colin Ihrig 這個(gè)教程:JavaScript Closures Demystified

也就是說(shuō),代碼打印兩次You clicked element #NODES_LENGTH,其中NODES_LENGTH是nodes的結(jié)點(diǎn)個(gè)數(shù)。原因是在for循環(huán)完成后,變量i的值等于節(jié)點(diǎn)列表的長(zhǎng)度。此外,因?yàn)閕在代碼添加處理程序的作用域中,該變量屬于處理程序的閉包。你會(huì)記得,閉包中的變量的值不是靜態(tài)的,因此i的值不是添加處理程序時(shí)的值(對(duì)于列表來(lái)說(shuō),第一個(gè)按鈕為0,對(duì)于第二個(gè)按鈕為1,依此類推)。在處理程序?qū)⒈粓?zhí)行的時(shí)候,在控制臺(tái)上將打印變量i的當(dāng)前值,等于節(jié)點(diǎn)列表的長(zhǎng)度。

問題7: 閉包(Closures)

修復(fù)上題的問題,使得點(diǎn)擊第一個(gè)按鈕時(shí)輸出0,點(diǎn)擊第二個(gè)按鈕時(shí)輸出1,依此類推。

答案

有多種辦法可以解決這個(gè)問題,下面主要使用兩種方法解決這個(gè)問題。

第一個(gè)解決方案使用立即執(zhí)行函數(shù)表達(dá)式(IIFE)再創(chuàng)建一個(gè)閉包,從而得到所期望的i的值。實(shí)現(xiàn)此方法的代碼如下:

var nodes = document.getElementsByTagName("button");
for (var i = 0; i < nodes.length; i++) {
   nodes[i].addEventListener("click", (function(i) {
      return function() {
         console.log("You clicked element #" + i);
      }
   })(i));
}

另一個(gè)解決方案不使用IIFE,而是將函數(shù)移到循環(huán)的外面。這種方法由下面的代碼實(shí)現(xiàn):

function handlerWrapper(i) {
   return function() {
      console.log("You clicked element #" + i);
   }
}
 
var nodes = document.getElementsByTagName("button");
for (var i = 0; i < nodes.length; i++) {
   nodes[i].addEventListener("click", handlerWrapper(i));
}

問題8:數(shù)據(jù)類型

考慮如下代碼:

console.log(typeof null);
console.log(typeof {});
console.log(typeof []);
console.log(typeof undefined);

答案

前面的問題似乎有點(diǎn)傻,但它考察 typeof 操作符的知識(shí)。很多JavaScript開發(fā)人員不知道typeof的一些特性。在此示例中,控制臺(tái)將顯示以下內(nèi)容:

object
object
object
undefined

最令人驚訝的輸出結(jié)果可能是第三個(gè)。大多數(shù)開發(fā)人員認(rèn)為typeof []會(huì)返回Array。如果你想測(cè)試一個(gè)變量是否為數(shù)組,您可以執(zhí)行以下測(cè)試:

var myArray = [];
if (myArray instanceof Array) {
   // do something...
}
問題9:事件循環(huán)

下面代碼運(yùn)行結(jié)果是什么?請(qǐng)解釋。

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

答案

輸出結(jié)果:

1
4
3
2

想知道為什么輸出順序是這樣的,你需要弄了解setTimeout()做了什么,以及瀏覽器的事件循環(huán)原理。瀏覽器有一個(gè)事件循環(huán)用于檢查事件隊(duì)列,處理延遲的事件。UI事件(例如,點(diǎn)擊,滾動(dòng)等),Ajax回調(diào),以及提供給setTimeout()和setInterval()的回調(diào)都會(huì)依次被事件循環(huán)處理。因此,當(dāng)調(diào)用setTimeout()函數(shù)時(shí),即使延遲的時(shí)間被設(shè)置為0,提供的回調(diào)也會(huì)被排隊(duì)?;卣{(diào)會(huì)呆在隊(duì)列中,直到指定的時(shí)間用完后,引擎開始執(zhí)行動(dòng)作(如果它在當(dāng)前不執(zhí)行其他的動(dòng)作)。因此,即使setTimeout()回調(diào)被延遲0毫秒,它仍然會(huì)被排隊(duì),并且直到函數(shù)中其他非延遲的語(yǔ)句被執(zhí)行完了之后,才會(huì)執(zhí)行。

有了這些認(rèn)識(shí),理解輸出結(jié)果為“1”就容易了,因?yàn)樗呛瘮?shù)的第一句并且沒有使用setTimeout()函數(shù)來(lái)延遲。接著輸出“4”,因?yàn)樗菦]有被延遲的數(shù)字,也沒有進(jìn)行排隊(duì)。然后,剩下了“2”,“3”,兩者都被排隊(duì),但是前者需要等待一秒,后者等待0秒(這意味著引擎完成前兩個(gè)輸出之后馬上進(jìn)行)。這就解釋了為什么“3”在“2”之前。

問題10:算法

寫一個(gè)isPrime()函數(shù),當(dāng)其為質(zhì)數(shù)時(shí)返回true,否則返回false。

答案

我認(rèn)為這是面試中最常見的問題之一。然而,盡管這個(gè)問題經(jīng)常出現(xiàn)并且也很簡(jiǎn)單,但是從被面試人提供的答案中能很好地看出被面試人的數(shù)學(xué)和算法水平。

首先, 因?yàn)镴avaScript不同于C或者Java,因此你不能信任傳遞來(lái)的數(shù)據(jù)類型。如果面試官?zèng)]有明確地告訴你,你應(yīng)該詢問他是否需要做輸入檢查,還是不進(jìn)行檢查直接寫函數(shù)。嚴(yán)格上說(shuō),應(yīng)該對(duì)函數(shù)的輸入進(jìn)行檢查。

第二點(diǎn)要記?。贺?fù)數(shù)不是質(zhì)數(shù)。同樣的,1和0也不是,因此,首先測(cè)試這些數(shù)字。此外,2是質(zhì)數(shù)中唯一的偶數(shù)。沒有必要用一個(gè)循環(huán)來(lái)驗(yàn)證4,6,8。再則,如果一個(gè)數(shù)字不能被2整除,那么它不能被4,6,8等整除。因此,你的循環(huán)必須跳過(guò)這些數(shù)字。如果你測(cè)試輸入偶數(shù),你的算法將慢2倍(你測(cè)試雙倍數(shù)字)。可以采取其他一些更明智的優(yōu)化手段,我這里采用的是適用于大多數(shù)情況的。例如,如果一個(gè)數(shù)字不能被5整除,它也不會(huì)被5的倍數(shù)整除。所以,沒有必要檢測(cè)10,15,20等等。如果你深入了解這個(gè)問題的解決方案,我建議你去看相關(guān)的Wikipedia介紹。

最后一點(diǎn),你不需要檢查比輸入數(shù)字的開方還要大的數(shù)字。我感覺人們會(huì)遺漏掉這一點(diǎn),并且也不會(huì)因?yàn)榇硕@得消極的反饋。但是,展示出這一方面的知識(shí)會(huì)給你額外加分。

現(xiàn)在你具備了這個(gè)問題的背景知識(shí),下面是總結(jié)以上所有考慮的解決方案:

function isPrime(number) {
   // If your browser doesn"t support the method Number.isInteger of ECMAScript 6,
   // you can implement your own pretty easily
   if (typeof number !== "number" || !Number.isInteger(number)) {
      // Alternatively you can throw an error.
      return false;
   }
   if (number < 2) {
      return false;
   }
 
   if (number === 2) {
      return true;
   } else if (number % 2 === 0) {
      return false;
   }
   var squareRoot = Math.sqrt(number);
   for(var i = 3; i <= squareRoot; i += 2) {
      if (number % i === 0) {
         return false;
      }
   }
   return true;
}
問題11:數(shù)據(jù)類型
var a = {n : 1};
var b = a;
a.x = a = {n : 2};
console.log(a.x);  
console.log(b.x);

解析:

var a = {n : 1};
var b = a;
// 此時(shí)b = {n:1};
//如果此時(shí)a.n=4,那么b.n也等于4
a.x = a = {n : 2};
// 從右往左賦值,a = {n:2}; 新對(duì)象
// b = {n:2},//此時(shí)筆者認(rèn)為b應(yīng)該還是{n:1}待考證確認(rèn)
// a.x 中的a是{n:1}; {n:1}.x = {n:2}; 舊對(duì)象
// 因?yàn)閎和a是引用的關(guān)系所以b.x也等于 {n:2}
console.log(a.x); undefined
// 此時(shí)的a是新對(duì)象,新對(duì)象上沒有a.x 所以是undefined
console.log(b.x); {n:2}
var i = 10;
i += i *= i;

// i*=i 100
// i+= 這里的i是 =10不是100
console.log(i);
問題12:
if (!("a" in window)) {
    var a = 1;
}

console.log(a);

解析:

在瀏覽器環(huán)境中,全局變量都是window的一個(gè)屬性,即
var a = 1 等價(jià)于 window.a = 1。in操作符用來(lái)判斷某個(gè)屬性屬于某個(gè)對(duì)象,可以是對(duì)象的直接屬性,也可以是通過(guò)prototype繼承的屬性。

再看題目,在瀏覽器中,如果沒有全局變量 a ,則聲明一個(gè)全局變量 a (ES5沒有塊級(jí)作用域),并且賦值為1。很多人會(huì)認(rèn)為打印的是1。非也,大家不要忘了變量聲明會(huì)被前置!什么意思呢?題目也就等價(jià)于

var a;

if (!("a" in window)) {
    a = 1;
}

console.log(a);

所以其實(shí)已經(jīng)聲明了變量a,只不過(guò)if語(yǔ)句之前值是undefined,所以if語(yǔ)句壓根不會(huì)執(zhí)行。
最后答案就是 undefined

問題13:
var a = 1,
    b = function a(x) {
        x && a(--x);
    };
console.log(a);

解析:
這道題有幾個(gè)需要注意的地方:

1.變量聲明、函數(shù)聲明會(huì)被前置,但是函數(shù)表達(dá)式并不會(huì),準(zhǔn)確說(shuō)類似變量聲明前置,舉個(gè)栗子:

console.log("b", b); // b undefined
var b = function() {}
console.log("b", b); // b function () {}

2.具名的函數(shù)表達(dá)式的名字只能在該函數(shù)內(nèi)部取到,舉個(gè)例子(排除老的IE?):

var foo = function bar () {}

console.log("foo", foo); 
// foo function bar(){}

console.log("bar", bar);
// Uncaught ReferenceError: bar is not defined

綜合這兩點(diǎn),再看題目,最后輸出的內(nèi)容就為 1

問題14:
function a(x) {
    return x * 2;
}
var a;
console.log(a);

解析:
函數(shù)聲明會(huì)覆蓋變量聲明,但不會(huì)覆蓋變量賦值,舉個(gè)栗子簡(jiǎn)單粗暴:

function foo(){
    return 1;
}
var foo;
console.log(typeof foo);    // "function"

函數(shù)聲明的優(yōu)先級(jí)高于變量聲明的優(yōu)先級(jí),但如果該變量foo賦值了,那結(jié)果就完全不一樣了:

function foo(){
    return 1;
}
var foo = 1;
console.log(typeof foo);    // "number"

變量foo賦值以后,變量賦值初始化就覆蓋了函數(shù)聲明。這個(gè)需要注意
再看題目

function a(x) {
    return x * 2;
}
var a;
console.log(a); // function a(x) {...}
問題15:
function b(x, y, a) {
    arguments[2] = 10;
    console.log(a);
}
b(1, 2, 3);

解析:
這題考察 arguments 對(duì)象的用法(詳看JavaScript中的arguments對(duì)象)
一般情況,arguments與函數(shù)參數(shù)是動(dòng)態(tài)綁定關(guān)系(為什么說(shuō)是一般稍后會(huì)解釋),所以很好理解,最后輸出的是10

但是但是但是,我們不要忘了一個(gè)特殊情況–嚴(yán)格模式,在嚴(yán)格模式中 arguments 與相當(dāng)于函數(shù)參數(shù)的一個(gè)拷貝,并沒有動(dòng)態(tài)綁定關(guān)系,舉個(gè)栗子:

"use strict"
// 嚴(yán)格模式?。?
function b(x, y, a) {
    arguments[2] = 10;
    console.log(a);
}
b(1, 2, 3); // 3
問題16:
function a() {
    console.log(this);
}
a.call(null);

解析:

function a() {
    console.log(this);
}
a.call(null);

關(guān)于 a.call(null); 根據(jù)ECMAScript262規(guī)范規(guī)定:
如果第一個(gè)參數(shù)傳入的對(duì)象調(diào)用者是null或者undefined的話,call方法將把全局對(duì)象(瀏覽器上是window對(duì)象)作為this的值。所以,不管你什么時(shí)候傳入null或者 undefined,其this都是全局對(duì)象window。所以,在瀏覽器上答案是輸出 window 對(duì)象。

但是但是但是,我們依舊不能忘記一個(gè)特殊情況–嚴(yán)格模式,在嚴(yán)格模式中,null 就是 null,undefined 就是 undefined ,舉個(gè)栗子:

"use strict";
// 嚴(yán)格模式?。?
function a() {
    console.log(this);
}
a.call(null); // null
a.call(undefined); // undefined

參考文章:
1.10道典型的JavaScript面試題
2.對(duì)匿名函數(shù)的深入理解(徹底版) 見評(píng)論區(qū)
3.你真的知道JS嗎?

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/92023.html

相關(guān)文章

  • 幾道題考考你 JavaScript 作用域(80%的人回答不對(duì))

    摘要:定義變量如果不使用則變量為為全局作用域。當(dāng)然嚴(yán)格模式是禁止這樣做的。遵循詞法作用域原則,其中后兩題來(lái)源于權(quán)威指南。非箭頭函數(shù)下的指向運(yùn)行時(shí)所在作用域。中逗號(hào)操作符會(huì)從左到右計(jì)算它的操作數(shù),返回最后一個(gè)操作數(shù)的值。原文發(fā)表于我的博客 (function(){ var a = b =1; })() console.log(b) 答案:1。定義變量如果不使用 var 則變量為為全局作...

    Ilikewhite 評(píng)論0 收藏0
  • 為什么你學(xué)不會(huì)遞歸?刷題幾個(gè)月,告別遞歸,談?wù)勎业慕?jīng)驗(yàn)

    摘要:第一遞歸函數(shù)功能假設(shè)的功能是求第項(xiàng)的值,代碼如下找出遞歸結(jié)束的條件顯然,當(dāng)或者我們可以輕易著知道結(jié)果。定義遞歸函數(shù)功能假設(shè)函數(shù)的功能是反轉(zhuǎn)但鏈表,其中表示鏈表的頭節(jié)點(diǎn)??赡芎芏嗳嗽诖笠坏臅r(shí)候,就已經(jīng)接觸了遞歸了,不過(guò),我敢保證很多人初學(xué)者剛開始接觸遞歸的時(shí)候,是一臉懵逼的,我當(dāng)初也是,給我的感覺就是,遞歸太神奇了! 可能也有一大部分人知道遞歸,也能看的懂遞歸,但在實(shí)際做題過(guò)程中,卻不知道怎么...

    Achilles 評(píng)論0 收藏0
  • 開開心心做幾道JavaScript機(jī)試題 - 01

    摘要:碰到這種面試官,你只有是個(gè)題霸,再加上眼緣夠才能順利入圍。只要按照我題目的思路,甚至打出來(lái)測(cè)試用例看看,就能實(shí)現(xiàn)這個(gè)題目了。答案根據(jù)的,對(duì)答案做出修正。另我的答案絕不敢稱最佳,隨時(shí)歡迎優(yōu)化修正。但了解總歸是好的。 我們?cè)陂L(zhǎng)期的面試過(guò)程中,經(jīng)歷了種種苦不堪言,不訴苦感覺不過(guò)癮(我盡量控制),然后主要聊聊常見JavaScript面試題的解法,以及面試注意事項(xiàng) 憶苦 面試第一苦,面試官的土 ...

    liujs 評(píng)論0 收藏0
  • JavaScript 關(guān)于this的幾道面試題及介紹

    摘要:對(duì)象方法中的當(dāng)以對(duì)象里的方法的方式調(diào)用函數(shù)時(shí),它們的是調(diào)用該函數(shù)的對(duì)象。注意,在何處或者如何定義調(diào)用函數(shù)完全不會(huì)影響到的行為。在這次執(zhí)行期間,函數(shù)中的將指向。 原文鏈接 與其他語(yǔ)言相比,函數(shù)的this關(guān)鍵字在JavaScript中的行為略有不同。并且它在嚴(yán)格模式和非嚴(yán)格模式之間也有一些區(qū)別。 在絕大多數(shù)情況下,函數(shù)的調(diào)用方式?jīng)Q定了this的值。this不能在執(zhí)行期間被賦值,在每次函數(shù)被...

    lifefriend_007 評(píng)論0 收藏0
  • 幾道前端面試題小記

    摘要:全局環(huán)境調(diào)用函數(shù)的對(duì)象實(shí)際為,所以函數(shù)內(nèi)的指向構(gòu)造函數(shù)通過(guò)構(gòu)造函造函數(shù)生成了一個(gè)新對(duì)象,指向這個(gè)新對(duì)象。學(xué)習(xí)前端一個(gè)月,上一周面試了大概多家,收獲的卻是寥寥。為了效率,前端各方面的內(nèi)容都有涉獵,深度卻相當(dāng)不足,面試時(shí)暴露各種問題。 最近面試了不少家,苦于前端經(jīng)驗(yàn)薄弱,被各種血虐。做了不少家面試題,把各種不會(huì)的回來(lái)再做一遍,作為經(jīng)驗(yàn)總結(jié)吧。 1.如何最優(yōu)性能去重一個(gè)數(shù)組? 方法有好多,比...

    tulayang 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<