天天看點

每日20道面試題帶解析01 — (1 - 20)

每日20道面試題帶解析01 — (1 - 20)

以下面試目,本人驗證無誤,查閱了相關資料,得出解析部分并做了相關總結,希望對正準備跳槽或找工作的你有所幫助!

1、寫出執行結果
function side(arr) {
  arr[0] = arr[2];
}
function a(a, b, c) {
  c = 10;
  side(arguments);
  return a + b + c;
}
a(1, 1, 1);      

答案及解析

答案 : 21
解析 : 
    1. 調用 a 函數,abc 都是 1,
    2. 後 c 指派為10,
    3. 調 side 函數,參數 arguments對象,是形參abc的引用,此時 abc 為[1,1,10] 
    4. 給 arr[0] 指派,即 a = c = 10,
    5. 輸出結果 10 + 1 + 10 = 21      
2、題一稍加改動,寫出執行結果
function side(arr) {
  arr[0] = arr[2];
}
function a(a, b, c = 3) {
  c = 10;
  side(arguments);
  return a + b + c;
}
a(1, 1, 1);      

答案及解析

答案 : 12
解析 : arguments 中的 c 還是 1,不會變成10,因為 a 函數給了預設值,就按ES6的方式解析,ES6有塊級作用域,是以 c 的值是不會改變的。      
3、 寫出執行結果
var min = Math.min();
var max = Math.max();
console.log(min < max);  //會是什麼?      

答案及解析

答案 : false
解析 : 按正常思路,應該輸出 true,最小值小于最大值,但是卻是false,MDN是這樣解釋的:- Math.min(): 如果沒有參數,結果為 Infinity (無窮大)
    - Math.max(): 如果沒有參數,結果為 - Infinity (無窮小)    console.log(-0.0000000000001 > Math.max())    // true      
4、寫出執行結果,并解釋原因
var a = 1;
(function a(){
    a = 2
    console.log(a)
})()      

答案及解析

答案 : ƒ a(){
        a = 2
        console.log(a)
      }
解析 : IIFE: Immediately Invoked Function Expression 立即執行函數,存在的目的就是為了隔離作用域,防止污染全局命名空間。是以 IIFE 有自己獨立的作用域,如果函數名稱與内部變量名沖突,就會永遠執行函數本身,是以輸出函數本身
了解 : 
    1. 立即執行函數可以是匿名函數 ;(function(){ var ....})()
    2. 開始的第一個字元使用分号,避免出現代碼壓縮時産生意外的錯誤return reslut;(function(){...})(), 在省略分号之後,變成return 一個函數了
    3. 函數執行一對()的位置: ;(function(){....}())  效果同 ;(function(){....})() 常見為第二種      
5、 寫出執行結果,并解釋原因
var fullname = 'a';
var obj = {
   fullname: 'b',
   prop: {
      fullname: 'c',
      getFullname: function() {
         return this.fullname;
      }
   }
};


console.log(obj.prop.getFullname());     // ?
var test = obj.prop.getFullname;
console.log(test());           // ?      

答案及解析

答案 : c   a 
解析 : 在于運作時的this指向,取決于被誰調用,
    1. 第一問:getFullname 是作為obj.prop對象的方法被調用,此時執行環境就是該對象,即傳回 c
    2. 第二問:getFullname 被配置設定給test變量,此時執行環境是全局對象,window,即傳回 a      
6、寫出執行結果,并解釋原因
var company = {
    address: 'beijing'
}
var obj = Object.create(company);
delete obj.address
console.log(obj.address);      

答案及解析

答案 : c   a 
解析 : MDN解釋,Object.create()方法建立一個新對象,使用現有的對象來提供新建立的對象的__proto__。
Object.create(proto), 其中proto是 新建立對象的原型對象。
    - obj 通過prototype繼承了company 的address屬性,自己并沒有該屬性,是以delete操作符是沒有作用的
    - delete使用原則: 是用來删除一個對象的屬性,但僅限于在自身的屬性上起作用(不可操作原型上的屬性),若删除的屬性不存在,那麼delete将不會起作用,但仍會傳回true      
7、寫出執行結果,并解釋原因
var foo = function bar(){ return 12; };
console.log(typeof bar());      

答案及解析

答案 : 報錯 ReferenceError: bar is not defined
解析 : 命名函數表達式 函數隻能在函數體内有效
    var foo = function bar(){ 
        // foo 可用
        // bar 可用
        console.log(typeof bar); // function
    };
    // foo 可用
    // bar 不可用      
8、 寫出執行結果,并解釋原因
var x=1;
if(function f(){}){
    x += typeof f;
}
console.log(x)      

答案及解析

答案 : 1undefined
解析 : 兩點
    1. 函數聲明在運算符中其值為true,但是放在運算符中的函數聲明在執行階段是找不到的
    2. 未聲明的變量執行 typeof 不會報錯,而是傳回 undefined      
9、寫出執行結果,并解釋原因
function f(){
    return f;
}
 console.log(new f() instanceof f);      

 答案及解析

答案 : false
解析 : 
    - a instanceof b 用于檢測 a 是否是 b 的執行個體,檢測的是原型,檢測過程中會周遊 a 的原型鍊,直到找到 b 的 prototype,如果存在傳回true 否則傳回false
    - 本題中return f後,new f()其傳回的結果是 f 的函數對象,并不是一個執行個體,是以傳回false
    - 改動一下即可傳回true
  function f(){}
   console.log(new f() instanceof f); // true      
10、寫出執行結果,并解釋原因
var foo = {
    bar: function(){
        return this.baz;
    },
    baz:1
}
console.log(typeof (f=foo.bar)());      

答案及解析

答案 : undefined
解析 : 将foo.bar 指派給 f ,相當于f(),此時 this 指向 window      
11、寫出執行結果,并解釋原因
for (let i = 0; i < 3; i++) {
  setTimeout(() => console.log(i), 1);
}      

答案及解析

答案 : 0  1  2
解析 : 使用let聲明變量具有塊級作用域(塊是{}之間的任何内容)每次循環 i 将被建立為一個新值,并且每個值都會存在于循環内的塊級作用域
for (var i = 0; i < 3; i++) {
  setTimeout(() => console.log(i), 1);
}
// 3 3 3 
由于JS的中的事件執行機制,setTimeout函數真正被執行時,循環已經結束,由于是使用var聲明的變量 i ,
是以該值是全局的,在循環期間自增,執行setTimeout函數時,i = 3      
12、寫出執行結果,并解釋原因
const num = {
  a: 10,
  add() {
    return this.a + 2;
  },
  reduce: () => this.a -2;
};
console.log(num.add());
console.log(num.reduce());      

答案及解析

答案 : 12  NaN
解析 : add 是普通函數,reduce是箭頭函數,對于箭頭函數this指向是它所在的上下文環境(定義時的位置),
意味着調用reduce時,this指向的并不是num對象 而是window,且全局并沒有 a 屬性,傳回undefined,undefined - 2 傳回NaN      
13、 寫出執行結果,并解釋原因
const person = { name: "Echoyya" };


function sayHi(age) {
  return `${this.name} is ${age}`;
}
console.log(sayHi.call(person, 5));
console.log(sayHi.bind(person, 5));      

答案及解析

答案 : Echoyya is 5 ; 
        ƒ sayHi(age) {
          return `${this.name} is ${age}`;
        }
解析 : call, bind方法都可以改變this指向,但是 call方式會立即執行,bind方法傳回一個綁定函數,帶有執行上下文,但不會立即執行,需要在調用一下。      
14、 寫出執行結果,并解釋原因
["1", "2", "3"].map(parseInt);      

答案及解析

答案 : [1, NaN, NaN]
解析 : // 以上代碼等同于
["1", "2", "3"].map((item, index) => parseInt(item, index));
parseInt(string, radix) 解析一個字元串并傳回指定基數的十進制整數
radix是2-36之間的整數,表示被解析字元串的基數。
    - 該參數省略或其值為 0,則數字将以 10 為基礎來解析;
    - 如果以 “0x” 或 “0X” 開頭,将以 16 為基數;
    - 如果小于 2 或者大于 36,将傳回 NaN。
分步執行:parseInt('1',0),parseInt('2',1),parseInt('3',2),由于'3'不屬于二進制字元,傳回NaN      
15、寫出執行結果,并解釋原因
[typeof null, null instanceof Object]      

答案及解析

答案 : ['object', false]
解析 : 
    1. typeof傳回一個表示類型的字元串,typeof null 傳回'object'
    2. instanceof 用于檢測constructor.prototype是否存在于參數object的原型鍊上      
16、寫出執行結果,并解釋原因
var arr = [0,1];
arr[5] = 5;
newArr = arr.filter(function(x) { return x === undefined;});
console.log(newArr.length);  // ?      

答案及解析

答案 : 0
解析 : filter方法,為數組中每個元素調用一次callback,傳回一個由滿足條件的元素組成的新數組,callback隻會在已經指派的索引上被調用,
對于被删除或未被指派的索引不會被調用, arr[5]=5之後,arr的值為 [0, 1, empty × 3, 5],
索引為234的元素沒有初始化,并不存在于數組中,在callback函數調用時會跳過,是以沒有一個元素的值是undefined。      
17、寫出執行結果,并解釋原因
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'));      

答案及解析

答案 : Do not know!
解析 : switch 是嚴格比較,String執行個體和字元串不一樣
    var str1 = 'str';
    var str2 = new String('str')
    console.log(typeof str1) // 'string'
    console.log(typeof str2) // 'object'      
18、寫出執行結果,并解釋原因
console.log([2,1,0].reduce(Math.pow));  // ?
console.log([].reduce(Math.pow));       // ?


A. 2 報錯
B. 2 NaN
C. 1 報錯
D. 1 NaN      

答案及解析

答案 : C
解析 : reduce(callback, initialValue) 方法參數callback是一個回調函數,并作為累加器,數組中的每個值從左到右開始計算,最終傳回一個值。參數initialValue是累加器初始值
該回調函數可接收四個參數:total  必需。初始值, 或者計算結束後的傳回值。currentValue 必需。目前元素。currentIndex  可選。目前元素索引。arr 可選。目前元素所屬的數組對象。
而Math.pow 可接收兩個參數,即前兩個參數
分步執行得到:Math.pow(2,1) => 2 ,Math.pow(2,0) => 1,要有一些數學基礎哦,是以第一個console輸出 1 ,而第二個console将報錯TypeError: Reduce of empty array with no initial value,
原因是:if the array is empty and no initialValue was provided,TypeError would be thrown ,意思是說,若數組為空且沒有提供initialValue初始值,将會抛出TypeError      
19、寫出執行結果,并解釋原因
function Foo() {
    Foo.a = function() {
        console.log(1)
    }
    this.a = function() {
        console.log(2)
    }
}
Foo.prototype.a = function() {
    console.log(3)
}
Foo.a = function() {
    console.log(4)
}
Foo.a();    // ?
let obj = new Foo();
obj.a();    // ?
Foo.a();    // ?      

答案及解析

答案 : 4  2  1 
解析 : 
    1. Foo.a():調用 Foo 的靜态方法 a,雖然 Foo 中有優先級更高的屬性方法 a,但 Foo 此時沒有被調用,是以此時輸出 Foo 的靜态方法 a 的結果:4
    2. let obj = new Foo(); 使用 new 方法調用函數,傳回函數執行個體對象,此時 Foo 函數内部的屬性方法初始化,原型方法建立。
    3. obj.a(); 調用 執行個體方法 a,該執行個體目前有兩個 a 方法:一個内部屬性方法,一個原型方法。當兩者重名時,内部屬性方法優先級更高,會覆寫後者,是以輸出2
    4. Foo.a(); 根據第2步可知 Foo 函數内部的屬性方法已初始化,覆寫了同名的靜态方法,是以輸出:1      
20、寫出執行結果,并解釋原因
const value  = 'Value is' + !!Number(['0']) ? 'Echoyya' : 'undefined';
console.log(value);      

答案及解析

答案 : Echoyya
解析 : 
    1.  !!Number(['0']) 傳回false
    2. + 運算符優先級 大于 ? 運算符,
    是以該題目等價于 'Value is false' ? 'Echoyya' : 'undefined',而不是 'Value is (false' ? 'Echoyya' : 'undefined')