20個必會的JavaScript面試題

問題1:JavaScript 中 undefinednot defined 的區別

JavaScript 未聲明變量直接使用會拋出異常:var name is not defined,若是沒有處理異常,代碼就中止運行了。
可是,使用typeof undeclared_variable並不會產生異常,會直接返回 undefinedjavascript

var x; // 聲明 x
console.log(x); //output: undefined
console.log(typeof y); //output: undefined
console.log(z);  // 拋出異常: ReferenceError: z is not defined

問題2:下面的代碼輸出什麼?

var y = 1;
if (function f(){}) {
    y += typeof f;
}
console.log(y);

正確的答案應該是 1undefinedjava

JavaScript中if語句求值其實使用eval函數,eval(function f(){}) 返回 function f(){} 也就是 true面試

下面咱們能夠把代碼改造下,變成其等效代碼。chrome

var k = 1;
if (1) {
    eval(function foo(){});
    k += typeof foo;
}
console.log(k);

上面的代碼輸出其實就是 1undefined。爲何那?咱們查看下 eval() 說明文檔便可得到答案數組

該方法只接受原始字符串做爲參數,若是 string 參數不是原始字符串,那麼該方法將不做任何改變地返回。閉包

偏偏 function f(){} 語句的返回值是 undefined,因此一切都說通了。app

注意上面代碼和如下代碼不一樣。ide

var k = 1;
if (1) {
    function foo(){};
    k += typeof foo;
}
console.log(k); // output 1function

問題3:在JavaScript中建立一個真正的private方法有什麼缺點?

每個對象都會建立一個private方法的方法,這樣很耗費內存函數

觀察下面代碼this

var Employee = function (name, company, salary) {
    this.name = name || "";       
    this.company = company || ""; 
    this.salary = salary || 5000; 

    // Private method
    var increaseSalary = function () {
        this.salary = this.salary + 1000;
    };

    // Public method
    this.dispalyIncreasedSalary = function() {
        increaseSlary();
        console.log(this.salary);
    };
};

// Create Employee class object
var emp1 = new Employee("John","Pluto",3000);
// Create Employee class object
var emp2 = new Employee("Merry","Pluto",2000);
// Create Employee class object
var emp3 = new Employee("Ren","Pluto",2500);

在這裏 emp1,emp2,emp3都有一個increaseSalary私有方法的副本。

因此咱們除非必要,很是不推薦使用私有方法。

問題4:JavaScript中什麼是閉包?寫出一個例子

老生常談的問題了,閉包是在一個函數裏聲明瞭另一個函數,而且這個函數訪問了父函數做用域裏的變量。

下面給出一個閉包例子,它訪問了三個域的變量

  • 它本身做用域的變量

  • 父函數做用域的變量

  • 全局做用域的變量

var globalVar = "abc"; 

// Parent self invoking function 
(function outerFunction (outerArg) { // begin of scope outerFunction
    // Variable declared in outerFunction function scope 
    var outerFuncVar = 'x';    
    // Closure self-invoking function 
    (function innerFunction (innerArg) { // begin of scope innerFunction
        // variable declared in innerFunction function scope
        var innerFuncVar = "y"; 
        console.log(          
            "outerArg = " + outerArg + "\n" +
            "outerFuncVar = " + outerFuncVar + "\n" +
            "innerArg = " + innerArg + "\n" +
            "innerFuncVar = " + innerFuncVar + "\n" +
            "globalVar = " + globalVar);
 
    }// end of scope innerFunction)(5); // Pass 5 as parameter 
}// end of scope outerFunction )(7); // Pass 7 as parameter 
innerFunction is closure that is defined inside outerFunc

輸出很簡單:

outerArg = 7
outerFuncVar = x
innerArg = 5
innerFuncVar = y
globalVar = abc

問題5:寫一個mul函數,使用方法以下。

console.log(mul(2)(3)(4)); // output : 24 
console.log(mul(4)(3)(4)); // output : 48

答案直接給出:

function mul (x) {
    return function (y) { // anonymous function 
        return function (z) { // anonymous function 
            return x * y * z; 
        };
    };
}

簡單說明下: mul 返回一個匿名函數,運行這個匿名函數又返回一個匿名函數,最裏面的匿名函數能夠訪問 x,y,z 進而算出乘積返回便可。

對於JavaScript中的函數通常能夠考察以下知識點:

  • 函數是一等公民

  • 函數能夠有屬性,而且能鏈接到它的構造方法

  • 函數能夠像一個變量同樣存在內存中

  • 函數能夠當作參數傳給其餘函數

  • 函數能夠返回其餘函數

問題6:JavaScript怎麼清空數組?

var arrayList =  ['a','b','c','d','e','f'];

怎麼清空 arrayList

方法1

arrayList = [];

直接改變arrayList所指向的對象,原對象並不改變。

方法2

arrayList.length = 0;

這種方法經過設置length=0 使原數組清除元素。

方法3

arrayList.splice(0, arrayList.length);

和方法2類似

問題7:怎麼判斷一個object是不是數組(array)?

方法1

使用 Object.prototype.toString 來判斷是不是數組

function isArray(obj){
    return Object.prototype.toString.call( obj ) === '[object Array]';
}

這裏使用call來使 toString 中 this 指向 obj。進而完成判斷

方法二

使用 原型鏈 來完成判斷

function isArray(obj){
    return obj.__proto__ === Array.prototype;
}

基本思想是利用 實例若是是某個構造函數構造出來的那麼 它的 __proto__是指向構造函數的 prototype屬性。

方法3

利用JQuery

function isArray(obj){
    return $.isArray(obj)
}

JQuery isArray 的實現其實就是方法1

問題8:下面代碼輸出什麼?

var output = (function(x){
    delete x;
    return x;
})(0);
  
console.log(output);

輸出是 0delete 操做符是將object的屬性刪去的操做。可是這裏的 x 是並非對象的屬性, delete 操做符並不能做用。

問題9:下面代碼輸出什麼?

var x = 1;
var output = (function(){
    delete x;
    return x;
})();

console.log(output);

輸出是 1delete 操做符是將object的屬性刪去的操做。可是這裏的 x 是並非對象的屬性, delete 操做符並不能做用。

問題10:下面代碼輸出什麼?

var x = { foo : 1};
var output = (function(){
    delete x.foo;
    return x.foo;
})();

console.log(output);

輸出是 undefined。x雖然是全局變量,可是它是一個object。delete做用在x.foo上,成功的將x.foo刪去。因此返回undefined

問題11:下面代碼輸出什麼?

var Employee = {
    company: 'xyz'
}
var emp1 = Object.create(Employee);
delete emp1.company
console.log(emp1.company);

輸出是 xyz,這裏的 emp1 經過 prototype 繼承了 Employee的 company。emp1本身並無company屬性。因此delete操做符的做用是無效的。

問題12:什麼是 undefined x 1

在chrome下執行以下代碼,咱們就能夠看到undefined x 1的身影。

var trees = ["redwood","bay","cedar","oak","maple"];
delete trees[3];
console.log(trees);

當咱們使用 delete 操做符刪除一個數組中的元素,這個元素的位置就會變成一個佔位符。打印出來就是undefined x 1
注意若是咱們使用trees[3] === 'undefined × 1'返回的是 false。由於它僅僅是一種打印表示,並非值變爲undefined x 1

問題13:下面代碼輸出什麼?

var trees = ["xyz","xxxx","test","ryan","apple"];
delete trees[3];
  
console.log(trees.length);

輸出是5。由於delete操做符並非影響數組的長度。

問題14:下面代碼輸出什麼?

var bar = true;
console.log(bar + 0);   
console.log(bar + "xyz");  
console.log(bar + true);  
console.log(bar + false);

輸出是

1
truexyz
2
1

下面給出一個加法操做表

  • Number + Number -> 加法

  • Boolean + Number -> 加法

  • Boolean + Boolean -> 加法

  • Number + String -> 鏈接

  • String + Boolean -> 鏈接

  • String + String -> 鏈接

問題15:下面代碼輸出什麼?

var z = 1, y = z = typeof y;
console.log(y);

輸出是 undefined。js中賦值操做結合律是右至左的 ,即從最右邊開始計算值賦值給左邊的變量。

上面代碼等價於

var z = 1
z = typeof y;
var y = z;
console.log(y);

問題16:下面代碼輸出什麼?

var foo = function bar(){ return 12; };
typeof bar();

輸出是拋出異常,bar is not defined。
若是想讓代碼正常運行,須要這樣修改代碼:

var bar = function(){ return 12; };
typeof bar();

或者是

function bar(){ return 12; };
typeof bar();

明確說明這個下問題

var foo = function bar(){ 
    // foo is visible here 
    // bar is visible here
    console.log(typeof bar()); // Work here :)
};
// foo is visible here
// bar is undefined here

問題17:兩種函數聲明有什麼區別?

var foo = function(){ 
    // Some code
}; 
function bar(){ 
    // Some code
};

foo的定義是在運行時。想系統說明這個問題,咱們要引入變量提高的這一律念。

咱們能夠運行下以下代碼看看結果。

console.log(foo)
console.log(bar)

var foo = function(){ 
    // Some code
}; 
function bar(){ 
    // Some code
};

輸出爲

undefined
function bar(){ 
    // Some code
};

爲何那?爲何 foo 打印出來是 undefined,而 bar打印出來倒是函數?

JavaScript在執行時,會將變量提高。

因此上面代碼JavaScript 引擎在實際執行時按這個順序執行。

// foo bar的定義位置被提高
function bar(){ 
    // Some code
}; 
var foo;

console.log(foo)
console.log(bar)

foo = function(){ 
    // Some code
};

原代碼的輸出合理解釋了。

問題18:下面代碼輸出什麼?

var salary = "1000$";

(function () {
    console.log("Original salary was " + salary);

    var salary = "5000$";

    console.log("My New Salary " + salary);
})();

輸出是

Original salary was undefined
My New Salary 5000$

這題一樣考察的是變量提高。等價於如下代碼

var salary = "1000$";

 (function () {
     var salary ;
     console.log("Original salary was " + salary);

     salary = "5000$";

     console.log("My New Salary " + salary);
 })();

問題19:什麼是 instanceof 操做符?下面代碼輸出什麼?

function foo(){ 
  return foo; 
}

console.log(new foo() instanceof foo);

instanceof操做符用來判斷是否當前對象是特定類的對象。

function Animal(){
    //或者不寫return語句
    return this;
}
var dog = new Animal();
dog instanceof Animal // Output : true

可是,這裏的foo定義爲

function foo(){ 
  return foo; 
}

因此

// here bar is pointer to function foo(){return foo}.
var bar = new foo();

因此 new foo() instanceof foo 返回 false

問題20: 若是咱們使用JavaScript的"關聯數組",咱們怎麼計算"關聯數組"的長度?

var counterArray = {
    A : 3,
    B : 4
};
counterArray["C"] = 1;

其實答案很簡單,直接計算key的數量就能夠了。

Object.keys(counterArray).length // Output 3

面試題參考自: 21 Essential JavaScript Interview Questions | Codementor

本文給出的面試題答案只是不少合理答案中的幾個,可能會不全面,歡迎你們補充。

因爲我的疏忽等緣由,本文中不免會存在少許錯誤,歡迎你們批評指正。

相關文章
相關標籤/搜索