「查缺補漏」送你 54 道 JavaScript 面試題

前言

你們好,我叫TianTian,一個愛瞎折騰,愛算法的Acmer愛好者,梳理一些比較好的JS題目,複習完仍是收穫很大,分享給你們❤️javascript

題目主要來自看到過的易錯題,還有經典的44道 JavaScript Puzzlers!,出自原文連接html

stackoverflow 這上面有不少Questions不錯的,能夠好好補一補基礎java

JS易錯題暫時很長一段時間就不更新啦,TypeScript都出來了,TS真香git

➡️給個小建議,能夠先看完第一題,要是沒有問題的話,後面的基本上也能夠跳過github

GitHub倉庫點這裏面試

開始吧👇算法

「查缺補漏」送你18道瀏覽器面試題(1.6W字)chrome

. VS = 操做符優先級

let a = {n : 1};
 let b = a;  a.x = a = {n: 2};    console.log(a.x)  console.log(b.x) 複製代碼

輸出是什麼呢?數組

真的想明白了嗎?瀏覽器

答案

undefined


{ n : 2}

你真的瞭解做用域嗎

var a = 0,  
 b = 0;  function A(a) {  A = function (b) {  console.log(a + b++)  }  console.log(a++)  }  A(1)  A(2) 複製代碼

留給大家思考,我但是第一遍就作錯了(;′⌒`)

答案 1 4

能夠好好想想,你會茅塞頓開的。

類數組的length

var obj = {
 "2" : 3,  "3" : 4,  "length" : 2,  "splice" : Array.prototype.splice,  "push" : Array.prototype.push  }  obj.push(1)  obj.push(2)  console.log(obj) 複製代碼

這段代碼的執行結果?

答案:Object(4) [empty × 2, 1, 2, splice: ƒ, push: ƒ]
複製代碼
類數組length
類數組length
解釋就是第一次使用push,obj對象的push方法設置obj[2] = 1,obj.length++
 解釋就是第一次使用push,obj對象的push方法設置obj[3] = 2,obj.length++  使用console.log()方法輸出的時候,由於obj上有length屬性和splice方法,故將其做爲數組輸出打印  打印時由於數組未設置下標爲0和1的值,故打印的結果就是empty,主動獲取obj[0] = undefined  複製代碼

非匿名自執行函數,函數名只讀

var b = 10;
 (function b(){  // 'use strict'  b = 20  console.log(b)  })() 複製代碼

輸出的結果是什麼?

Function b
複製代碼
- 如標題同樣,非匿名自執行函數,函數名不能夠修改,嚴格模式下會TypeError,
- 非嚴格模式下,不報錯,修改也沒有用。 - 查找變量b時,當即執行函數會有內部做用域,會先去查找是否有b變量的聲明,有的話,直接複製 - 確實發現具名函數Function b(){} 因此就拿來作b的值 - IIFE的函數內部沒法進行復制(相似於const) 複製代碼

非匿名自執行函數 II

var b = 10;
 (function b(){  // 'use strict'  var b = 20  console.log(window.b)  console.log(b)  })() 複製代碼

輸出是多少呢?

10
20 // 訪問b變量的時候,發現var b = 20;在當前做用域中找到了b變量,因而把b的值做爲20 複製代碼

非匿名自執行函數 III

var b = 10;
 (function b(){  console.log(b)  b = 5  console.log(window.b)  var b = 20  console.log(b)  })() 複製代碼

輸出的結果是多少呢?

這個問題應該不難,就留給大家思考吧

變量提高

var name = 'World!';
(function () {  if (typeof name === 'undefined') {  var name = 'Jack';  console.log('Goodbye ' + name);  } else {  console.log('Hello ' + name);  } })(); 複製代碼

在 JavaScript中, Fun 和 var 會被提高

至關於

var name = 'World!';
(function () {  var name;  if (typeof name === 'undefined') {  name = 'Jack';  console.log('Goodbye ' + name);  } else {  console.log('Hello ' + name);  } })(); 複製代碼

鞏固一下:

var str = 'World!';   
 (function (name) {  if (typeof name === 'undefined') {  var name = 'Jack';  console.log('Goodbye ' + name);  } else {  console.log('Hello ' + name);  }  })(str);  答案:Hello World 由於name已經變成函數內局部變量 複製代碼

最大整數

var END = Math.pow(2, 53);
var START = END - 100; var count = 0; for (var i = START; i <= END; i++) {  count++; } console.log(count); 複製代碼

一個知識點:Infinity

在 JS 裏, Math.pow(2, 53) == 9007199254740992 是能夠表示的最大值. 最大值加一仍是最大值. 因此循環不會停.
複製代碼

稀疏數組與密數組

var ary = [0,1,2];
ary[10] = 10; ary.filter(function(x) { return x === undefined;}); 複製代碼

執行結果如何呢?

作這個題目,你須要瞭解稀疏數組和密集數組

看過源碼的同窗應該知道,filter源碼中,會去判斷數組的這個索引值是否是數組的一個屬性,有興趣的同窗能夠看看我寫的這篇關於數組的:[乾貨👍]從詳細操做js數組到淺析v8中array.js

0 in ary; => true
3 in ary; => false 10 in ary; => true 也就是說 從 3 - 9 都是沒有初始化的'坑'!, 這些索引並不存在與數組中. 在 array 的函數調用的時候是會跳過這些'坑'的. 複製代碼

因此答案就是[]

浮點運算

var two   = 0.2
var one = 0.1 var eight = 0.8 var six = 0.6 [two - one == one, eight - six == two] 複製代碼

你認爲結果是多少呢?面試遇到這個問題,應該怎麼回答呢?

[true,false]
複製代碼

能夠看看這些文章:

Switch

function showCase(value) {
 switch(value) {  case 'A':  console.log('Case A');  break;  case 'B':  console.log('Case B');  break;  case undefined:  console.log('undefined');  break;  default:  console.log('Do not know!');  } } showCase(new String('A')); 複製代碼

運行結果如何呢?

switch 是嚴格比較, String 實例和 字符串不同.
答案天然是'Do not know' 因此通常狀況下,寫switch語句,也建議寫default 複製代碼

String("A")

function showCase2(value) {
 switch(value) {  case 'A':  console.log('Case A');  break;  case 'B':  console.log('Case B');  break;  case undefined:  console.log('undefined');  break;  default:  console.log('Do not know!');  } } showCase2(String('A')); 複製代碼

運行結果呢?

答案:Case A
解析:String('A')就是返回一個字符串  複製代碼

%運算符

function isOdd(num) {
 return num % 2 == 1; } function isEven(num) {  return num % 2 == 0; } function isSane(num) {  return isEven(num) || isOdd(num); } var values = [7, 4, '13', -9, Infinity]; values.map(isSane);  複製代碼

運行的結果如何呢?

答案:[true, true, true, false, false]
解析:%若是不是數值會調用Number()去轉化  '13' % 2 // 1  Infinity % 2 //NaN Infinity 是無窮大  -9 % 2 // -1 鞏固: 9 % -2 // 1 餘數的正負號隨第一個操做數 複製代碼

數組的原型是什麼

Array.isArray( Array.prototype )
複製代碼

這段代碼的執行結果?

答案:true
解析:Array.prototype是一個數組 數組的原型是數組,對象的原型是對象,函數的原型是函數 複製代碼

寬鬆相等 ==

[]==[]
複製代碼

答案是什麼呢

答案:false
解析:兩個引用類型, ==比較的是引用地址 複製代碼

== 和 !優先級

[]== ![] 
複製代碼

結果是什麼呢?

(1)! 的優先級高於== ,右邊Boolean([])是true,取返等於 false
(2)一個引用類型和一個值去比較 把引用類型轉化成值類型,左邊0 (3)因此 0 == false 答案是true 複製代碼

數字與字符串相加減

'5' + 3
'5' - 3 複製代碼

結果是多少呢?

答案:53  2
解析:加號有拼接功能,減號就是邏輯運算 鞏固:typeof (+"1") // "number" 對非數值+—常被用來作類型轉換至關於Number() 複製代碼

一波騷操做 + - + + + - +

1 + - + + + - + 1
複製代碼

結果是多少呢

答案:2
解析:+-又是一元加和減操做符號,就是數學裏的正負號。負負得正哈。 鞏固: 一元運算符還有一個經常使用的用法就是將自執行函數的function從函數聲明變成表達式。  經常使用的有 + - ~ ! void  + function () { }  - function () { }  ~ function () { }  void function () { } 複製代碼

又是稀疏數組? Array.prototype.map()

var ary = Array(3);
ary[0]=2 ary.map(function(elem) { return '1'; }); 複製代碼

輸出結果是多少呢?

稀疏數組
 題目中的數組實際上是一個長度爲3, 可是沒有內容的數組, array 上的操做會跳過這些未初始化的'坑'.  因此答案是 ["1", empty × 2] 複製代碼

這裏貼上 Array.prototype.map 的 polyfill.

Array.prototype.map = function(callback, thisArg) {
  var T, A, k;   if (this == null) {  throw new TypeError(' this is null or not defined');  }   var O = Object(this);  var len = O.length >>> 0;  if (typeof callback !== 'function') {  throw new TypeError(callback + ' is not a function');  }  if (arguments.length > 1) {  T = thisArg;  }  A = new Array(len);  k = 0;  while (k < len) {  var kValue, mappedValue;  if (k in O) {  kValue = O[k];  mappedValue = callback.call(T, kValue, k, O);  A[k] = mappedValue;  }  k++;  }  return A;  }; 複製代碼

JS是如何存儲

var a = 111111111111111110000,
b = 1111; a + b; 複製代碼

這段代碼的執行結果?

答案:11111111111111111000
解析:在JavaScript中number類型在JavaScript中以64位(8byte)來存儲。 這64位中有符號位1位、指數位11位、實數位52位。 2的53次方時,是最大值。 其值爲:9007199254740992(0x20000000000000)。 超過這個值的話,運算的結果就會不對. 複製代碼

數組比較大小

var a = [1, 2, 3],
 b = [1, 2, 3],  c = [1, 2, 4] a == b a === b a > c a < c 複製代碼

這段代碼的執行結果?

答案:false, false, false, true
解析:相等(==)和全等(===)仍是比較引用地址  引用類型間比較大小是按照字典序比較,就是先比第一項誰大,相同再去比第二項。 複製代碼

三元運算符優先級

var val = 'smtg';
console.log('Value is ' + (val === 'smtg') ? 'Something' : 'Nothing'); 複製代碼

這段代碼的執行結果?

答案:Something
解析:字符串鏈接比三元運算有更高的優先級  因此原題等價於 'Value is true' ? 'Somthing' : 'Nonthing'  而不是 'Value is' + (true ? 'Something' : 'Nonthing') 鞏固:  1 || fn() && fn() //1  1 || 1 ? 2 : 3 ; //2 複製代碼

原型

var a = {}, b = Object.prototype;
[a.prototype === b, Object.getPrototypeOf(a) === b] 複製代碼

執行結果是多少呢

答案:false, true
解析:Object 的實例是 a,a上並無prototype屬性  a的__poroto__ 指向的是Object.prototype,也就是Object.getPrototypeOf(a)。a的原型對象是b 複製代碼

原型II

function f() {}
var a = f.prototype, b = Object.getPrototypeOf(f); a === b 複製代碼

這段代碼的執行結果?

答案:false
解析:a是構造函數f的原型 : {constructor: ƒ} b是實例f的原型對象 : ƒ () { [native code] } 複製代碼

函數名稱

function foo() { }
var oldName = foo.name; foo.name = "bar"; [oldName, foo.name] 複製代碼

代碼執行結果是什麼?

答案:["foo", "foo"]
解析:函數的名字不可變. 複製代碼

[typeof null, null instanceof Object]

答案:["object", false]
解析:null表明空對象指針,因此typeof判斷成一個對象。能夠說JS設計上的一個BUG  instanceof 實際上判斷的是對象上構造函數,null是空固然不可能有構造函數 鞏固:null == undefined //true null === undefined //flase 複製代碼

[ [3,2,1].reduce(Math.pow), [].reduce(Math.pow) ]

答案:Error
解析:Math.pow (x , y) x 的 y 次冪的值  reduce(fn,total)  fn (total, currentValue, currentIndex, arr)  若是一個函數不傳初始值,數組第一個組默認爲初始值.  [3,2,1].reduce(Math.pow)  Math.pow(3,2) //9  Math.pow(9,1) //9  鞏固題,能夠作一作:  [].reduce(Math.pow) //空數組會報TypeError  [1].reduce(Math.pow) //只有初始值就不會執行回調函數,直接返回1  [].reduce(Math.pow,1) //只有初始值就不會執行回調函數,直接返回1  [2].reduce(Math.pow,3) //傳入初始值,執行回調函數,返回9 複製代碼

replace

"1 2 3".replace(/\d/g, parseInt)
複製代碼

輸出是什麼呢?

答案:"1 NaN 3"
解析:replace() 回調函數的四個參數:  一、匹配項  二、與模式中的子表達式匹配的字符串  三、出現的位置  四、stringObject 自己 。 若是沒有與子表達式匹配的項,第二參數爲出現的位置.因此第一個參數是匹配項,第二個參數是位置  parseInt('1', 0)  parseInt('2', 2) //2進制中不可能有2  parseInt('3', 4) 複製代碼

eval用法

function f() {}
var parent = Object.getPrototypeOf(f); f.name // ? parent.name // ? typeof eval(f.name) // ? typeof eval(parent.name) // ?  複製代碼

這段代碼的執行結果?

答案:"f", "Empty", "function", error
解析:f的函數名就是f  parent是f原型對象的名字爲"" ,  先計算eval(f.name) 爲 f,f的數據類型是function  eval(parent.name) 爲undefined, "undefined" 複製代碼

new Date()

var a = new Date("2014-03-19"),
b = new Date(2014, 03, 19); [a.getDay() === b.getDay(), a.getMonth() === b.getMonth()] 複製代碼

這段代碼的執行結果?

答案:[false, false]
解析: var a = new Date("2014-03-19") //可以識別這樣的字符串,返回想要的日期  Wed Mar 19 2014 08:00:00 GMT+0800 (CST)  b = new Date(2014, 03, 19); //參數要按照索引來  Sat Apr 19 2014 00:00:00 GMT+0800 (CST)  月是從0索引,日期是從1  getDay()是獲取星期幾  getMonth()是獲取月份因此都不一樣 鞏固: [a.getDate() === b.getDate()] //true 複製代碼

new Date() II

var a = Date(0);
var b = new Date(0); var c = new Date(); [a === b, b === c, a === c] 複製代碼

這段代碼的執行結果?

答案:[false, false, false]
解析:當日期被做爲構造函數調用時,它返回一個相對於劃時代的對象(JAN 01 1970)。 當參數丟失時,它返回當前日期。當它做爲函數調用時,它返回當前時間的字符串表示形式。 a是字符串 a === b // 數據類型都不一樣,確定是false b是對象 b === c // 引用類型,比的是引用地址 c也是對象 a === c // 數據類型都不一樣,確定是false 複製代碼

new Date() III

var a = new Date("epoch")
複製代碼

你認爲結果是多少呢?

答案:Invalid Date {}
解析:您獲得「無效日期」,這是一個實際的日期對象(一個日期的日期爲true)。但無效。這是由於時間內部保持爲一個數字,在這種狀況下,它是NA。  在chrome上是undefined  正確的是格式是var d = new Date(year, month, day, hours, minutes, seconds, milliseconds); 複製代碼

Function.length

var a = Function.length,
b = new Function().length a === b 複製代碼

這段代碼的執行結果是?

答案:false
解析:首先new在函數帶()時運算優先級和.同樣因此從左向右執行  new Function() 的函數長度爲0 鞏固:function fn () {  var a = 1;  }  console.log(fn.length)  //0 fn和new Function()同樣 複製代碼

要是看過往期的這篇文章[誠意滿滿✍]帶你填一些JS容易出錯的坑 就能夠給我點個贊👍關注一下啦,下面的內容都是這篇文章的內容。

[1,2,5,10].sort()

不寫回調函數的話,是按照什麼排序呢?

JavaScript默認使用字典序(alphanumeric)來排序。所以結果是[1,10,2,5]

正確排序的話,應該[1,2,5,10].sort( (a,b) => a-b )

"b" + "a" + +"a" + "a"

你認爲輸出是什麼?

上面的表達式至關於'b'+'a'+ (+'a')+'a',由於(+'a')是NaN,因此:

'b'+'a'+ (+'a')+'a' = 'b'+'a'+ "NaN"+'a'='baNaNa'

閉包

這是一個經典JavaScript面試題

let res = new Array()
 for(var i = 0; i < 10; i++){  res.push(function(){  return console.log(i)  })  }  res[0]()  res[1]()  res[2]() 複製代碼

指望輸出的是0,1,2,實際上卻不會。緣由就是涉及做用域,怎麼解決呢?

  • [x] 使用let代替var,造成塊級做用域
  • [x] 使用bind函數。
res.push(console.log.bind(null, i))
複製代碼

解法還有其餘的,好比使用IIFE,造成私有做用域等等作法。

又一經典閉包問題

function fun(n,o) {
 console.log(o)  return {  fun:function(m){  return fun(m,n);  }  }; } var a = fun(0); a.fun(1); a.fun(2); a.fun(3);//undefined,?,?,? var b = fun(0).fun(1).fun(2).fun(3);//undefined,?,?,? var c = fun(0).fun(1); c.fun(2); c.fun(3);//undefined,?,?,? 複製代碼

留給大家思考

隱式轉換

var a = [0];
if (a) {  console.log(a == true); } else {  console.log("wut"); } 複製代碼

大家以爲答案是多少呢?這題涉及到隱式轉換了,這個坑我本身的好好補一補

// 答案:false

再來一道?

function fn() {
 return 20; } console.log(fn + 10); // 輸出結果是多少 複製代碼
function fn() {
 return 20; } fn.toString = function() {  return 10; } console.log(fn + 10); // 輸出結果是多少? 複製代碼
function fn() {
 return 20; }  fn.toString = function() {  return 10; }  fn.valueOf = function() {  return 5; }  console.log(fn + 10); // 輸出結果是多少? 複製代碼

說到底JS類型轉換的好好補一補了

你真的理解操做符嗎

[1<2<3,3<2<1]
//[false,false] //[true,true] //[false,true] //[true,false] 複製代碼

選一個吧,比較操做符,賦值運算符優先級哪一個更高呢?

0.1+0.2 !== 0.3 ?

面試的時候,問你這個問題,要是回答錯誤的話,估計面試官對基礎非常懷疑!!!

問你這個題目的時候,你能夠牽扯出不少問題,好比JS如何存儲小數的呢?好比聊一聊二進制,好比實際開發中,遇到精度的問題,你是怎麼解決的,你有什麼好辦法。

聊完這個,你能夠牽扯出最大安全數,好比JavaScript的最大安全整數是多少,超出這個範圍的話,怎麼解決精度問題呢?

ES規範中新提出的BigInt解決了什麼問題呢,你又發現了BigInt中哪些坑呢?

如何解決精度問題呢?

這裏推薦Number-Precision庫,不到1K的體積。

arguments

function sidEffecting(ary) {
 ary[0] = ary[2];  }  function bar(a, b, c) {  c = 10  sidEffecting(arguments);  return a + b + c;  }  function demo (arg) {  arg.name = 'new Name'  }  console.log(bar(2, 2, 2)) 複製代碼

涉及到ES6語法,這題答案確定都會作是22,可是呢,稍微改變一下題目,就比較坑了….

function sidEffecting(ary) {
 ary[0] = ary[2];  }  function bar(a, b, c = 4) {  c = 10  sidEffecting(arguments);  return a + b + c;  }  function demo (arg) {  arg.name = 'new Name'  }  console.log(bar(2, 2, 2)) 複製代碼

這個答案是多少呢?根據MDN上對argument有更加準確的定義,看argument

當非嚴格模式中的函數包含剩餘參數默認參數解構賦值,那麼arguments對象中的值不會跟蹤參數的值(反之亦然)。

找到這句話,bar函數存在默認參數,而且在非嚴格模式下,因此不會跟蹤參數的值,天然結果就14

請讀者細細體會

瀏覽器懵逼史

let demo1 = {class: "Animal", name: 'sheet'};
 console.log(demo1.class) 複製代碼

比較流氓,這個跟瀏覽器相關,class是保留字(如今的話,class是關鍵字),答案並沒關係,重要的是本身在取屬性名稱的時候儘可能避免保留字. 若是使用的話請加引號 a['class']。

保留字vs關鍵字

我的理解的話,關鍵字就是有特殊含義的,不用用做變量名。好比

let class = 123;
複製代碼

如今看來確定報錯,那有什麼須要咱們注意的呢?

let undefined = 123;
複製代碼

這樣子並不會報錯,這個跟瀏覽器有點關係,這樣子看來undefined不是關鍵字。因此爲了保險起見,建議你們在判斷一個變量是否是未定義的話,儘可能使用void 0 === undefined 頗有可能undefined會被看成是變量來賦值

void 0 值就是undefined

["1", "2", "3"].map(parseInt)

這個應該是常常碰見的題了,搞明白很簡單,map函數怎麼使用,parseInt函數怎麼使用

關於Array數組的話,我以前寫了一篇文章,從源碼角度解析大部分方法

點進去重溫一遍:[乾貨👍]從詳細操做js數組到淺析v8中array.js

map接受兩個參數,一個callback,一個this,即調用函數時this指向,其中callback回調函數是三個參數,一個currentValue,index,array;

parseInt接受兩個參數:string,radix(基數)

返回NaN有兩種狀況

  • radix 小於 2 或大於 36 ,或
  • 第一個非空格字符不能轉換爲數字。
  • 當radix是0或者undefined時,又是特殊狀況,具體異步MDN
parseInt('1', 0);
parseInt('2', 1); parseInt('3', 2); 複製代碼

二者結合的話,結果天然很明顯,[1,NaN,NaN]

Math.min() 爲何比 Math.max() 大?

Math.min() < Math.max() // false
複製代碼

按照常規思路的話,應該是true,畢竟最小值應該小於最大值,可是實際狀況是false

緣由:

  • Math.min 的參數是 0 個或者多個。若是是多個參數很容易理解,返回參數中最小的。
  • 若是是0個參數,或者沒有參數,則返回 Infinity
  • 而 Math.max() 沒有傳遞參數時返回的是 -Infinity。

要是面試官問這個問題,額。。。。

[].concat[1,2,3]

輸出是什麼?注意不是[].concat([1,2,3])

// [1,2,3]
 // Uncaught SyntaxError: ....  // undefined 複製代碼

答案是undefined,緣由是什麼呢?

  1. 第一步計算[].concat,結果是Array.prototype.concat

  2. 第二步執行一個逗號操做符,逗號操做符對它的每一個操做對象求值(從左至右),而後返回最後一個操做對象的值。

    >1,2,3
    返回3 複製代碼
  3. 第三步執行一個數組訪問運算或屬性訪問運算

因此上面[].concat[1,2,3] 等價於Array.prototype.concat[3]

那麼結果天然就是 undefined

[1,2,NaN,3].indexOf(NaN)

//2 or -1

  • indexOf方法會進行嚴格相等判斷
  • NaN !== NaN

怎麼辦呢?

let realIsNaN = value => typeof value === 'number' && isNaN(value);
複製代碼

先要判斷類型,是由於字符串轉換會先轉換成數字,轉換失敗爲 NaN。因此和 NaN 相等。

isNaN('jjjj') —> true
複製代碼

第二種方法

let realIsNaN = value => value !== value;
複製代碼

Number.isFinite & isFinite

Number.isFinite('0') === isFinite('0')
 Number.isFinite(0) === isFinite('0') 複製代碼

打印結果是什麼,能不能具體說一說?

Number.isFinite()檢測有窮性的值,惟一和全局isFinite()函數相比,這個方法不會強制將一個非數值的參數轉換成數值,這就意味着,只有數值類型的值,且是有窮的(finite),才返回 true

天然答案就是 false,true

一道容易被人輕視的面試題

function Foo() {
 getName = function () { alert (1); };  return this; } Foo.getName = function () { alert (2);}; Foo.prototype.getName = function () { alert (3);}; var getName = function () { alert (4);}; function getName() { alert (5);}  //請寫出如下輸出結果: Foo.getName(); getName(); Foo().getName(); getName(); new Foo.getName(); new Foo().getName(); new new Foo().getName();  複製代碼

push方法

let newList = [1,2,3].push(4)
console.log(newList.push(4)) 複製代碼

認爲輸出什麼?

// Error

緣由在於Array.prototype.push()返回的是新數組的長度,因此呢4.push(5)天然Error


自動分號插入

function foo1() {  return {  bar: "hello"  }; }  function foo2() {  return  {  bar: "hello"  }; } var a=foo1(); var b=foo2(); console.log(a) //Object {bar: "hello"} console.log(b) //underfind //仔細看就知道了 // 會在第10行加入一個`;` 複製代碼

會在第10行自動加一個分號; 因此返回的就是undefined


let var

function foo() {
let a = b = 0; a++; return a; } foo(); typeof a; // => ??? typeof b; // => ???  複製代碼

上面的let a = b = 0; 等價於 window.b = 0, let a = b;


眼力題

const length = 4;
const numbers = []; for (var i = 0; i < length; i++);{  numbers.push(i + 1); }  numbers; // => ??? 複製代碼

惟一須要注意的就是for語句後面帶了;沙雕題

加了;,會認爲for執行完,因此指定的都是空語句,最後numbers爲[5]


獲取字符串中特定索引字符

console.log('Hello World'[4])
複製代碼

使用的就是方括號表示法獲取字符串特定索引的字符,值得注意的是,IE7低版本使用的是charAt()

因此這題輸出o


!==

const name = 'TianTianUp'
console.log(!typeof name === 'string') console.log(!typeof name === 'object') 複製代碼

typeof name 返回的是 ’string‘, 字符串’string‘是一個truthy值。所以!typeof name 返回一個布爾值false。因此

false === ’string'

和 false === ’object‘返回false

(檢測一個類型的值話,咱們應該使用 !==而不是!typeof)


forEach

const nums = [1, 2, 3, 4, 5, 6];
let firstEven; nums.forEach(n => {  if (n % 2 ===0 ) {  firstEven = n;  return n;  } }); console.log(firstEven); 複製代碼

惟一須要注意的就是forEach源碼是怎麼寫的,看過源碼的都知道,forEach使用return是不能停止循環的,或者說每一次調用callback函數,終止的是當前的一次,而不是整個循環。

結果天然就是6


❤️ 感謝你們

若是你以爲這篇內容對你挺有有幫助的話:

  1. 點贊支持下吧,讓更多的人也能看到這篇內容(收藏不點贊,都是耍流氓 -_-)

  2. 歡迎在留言區與我分享你的想法,也歡迎你在留言區記錄你的思考過程。

  3. 以爲不錯的話,也能夠看看往期文章:

    [ 「查缺補漏」送你18道瀏覽器面試題(1.6W字)

    [乾貨👍]從詳細操做js數組到淺析v8中array.js

    [1.2W字👍]寫給女朋友的祕籍-瀏覽器工做原理(上)篇

    [1.1W字]寫給女朋友的祕籍-瀏覽器工做原理(渲染流程)篇

    [建議👍]再來100道JS輸出題酸爽繼續(共1.8W字+鞏固JS基礎)

    「算法與數據結構」鏈表的9個基本操做

本文使用 mdnice 排版

相關文章
相關標籤/搜索