20個(gè)必會(huì)的JavaScript面試題(小結(jié))
問(wèn)題1:JavaScript 中 undefined 和 not defined 的區(qū)別
JavaScript 未聲明變量直接使用會(huì)拋出異常:var name is not defined,如果沒(méi)有處理異常,代碼就停止運(yùn)行了。 但是,使用typeof undeclared_variable并不會(huì)產(chǎn)生異常,會(huì)直接返回 undefined。
var x; // 聲明 x console.log(x); //output: undefined console.log(typeof y); //output: undefined console.log(z); // 拋出異常: ReferenceError: z is not defined
問(wèn)題2:下面的代碼輸出什么?
var y = 1; if (function f(){}) { y += typeof f; } console.log(y);
正確的答案應(yīng)該是 1undefined。
JavaScript中if語(yǔ)句求值其實(shí)使用eval函數(shù),eval(function f(){}) 返回 function f(){} 也就是 true。
下面我們可以把代碼改造下,變成其等效代碼。
var k = 1; if (1) { eval(function foo(){}); k += typeof foo; } console.log(k);
上面的代碼輸出其實(shí)就是 1undefined。為什么那?我們查看下 eval() 說(shuō)明文檔即可獲得答案
該方法只接受原始字符串作為參數(shù),如果 string 參數(shù)不是原始字符串,那么該方法將不作任何改變地返回。
恰恰 function f(){} 語(yǔ)句的返回值是 undefined,所以一切都說(shuō)通了。
注意上面代碼和以下代碼不同。
var k = 1; if (1) { function foo(){}; k += typeof foo; } console.log(k); // output 1function
問(wèn)題3:在JavaScript中創(chuàng)建一個(gè)真正的private方法有什么缺點(diǎn)?
每一個(gè)對(duì)象都會(huì)創(chuàng)建一個(gè)private方法的方法,這樣很耗費(fèi)內(nèi)存
觀察下面代碼
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都有一個(gè)increaseSalary私有方法的副本。
所以我們除非必要,非常不推薦使用私有方法。
問(wèn)題4:JavaScript中什么是閉包?寫(xiě)出一個(gè)例子
老生常談的問(wèn)題了,閉包是在一個(gè)函數(shù)里聲明了另外一個(gè)函數(shù),并且這個(gè)函數(shù)訪問(wèn)了父函數(shù)作用域里的變量。
下面給出一個(gè)閉包例子,它訪問(wèn)了三個(gè)域的變量
- 它自己作用域的變量
- 父函數(shù)作用域的變量
- 全局作用域的變量
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
輸出很簡(jiǎn)單:
outerArg = 7
outerFuncVar = x
innerArg = 5
innerFuncVar = y
globalVar = abc
問(wèn)題5:寫(xiě)一個(gè)mul函數(shù),使用方法如下。
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; }; }; }
簡(jiǎn)單說(shuō)明下: mul 返回一個(gè)匿名函數(shù),運(yùn)行這個(gè)匿名函數(shù)又返回一個(gè)匿名函數(shù),最里面的匿名函數(shù)可以訪問(wèn) x,y,z 進(jìn)而算出乘積返回即可。
對(duì)于JavaScript中的函數(shù)一般可以考察如下知識(shí)點(diǎn):
- 函數(shù)是一等公民
- 函數(shù)可以有屬性,并且能連接到它的構(gòu)造方法
- 函數(shù)可以像一個(gè)變量一樣存在內(nèi)存中
- 函數(shù)可以當(dāng)做參數(shù)傳給其他函數(shù)
- 函數(shù)可以返回其他函數(shù)
問(wèn)題6:JavaScript怎么清空數(shù)組?
如
var arrayList = ['a','b','c','d','e','f'];
怎么清空 arrayList
方法1
arrayList = [];
直接改變arrayList所指向的對(duì)象,原對(duì)象并不改變。
方法2
arrayList.length = 0;
這種方法通過(guò)設(shè)置length=0 使原數(shù)組清除元素。
方法3
arrayList.splice(0, arrayList.length);
和方法2相似
問(wèn)題7:怎么判斷一個(gè)object是否是數(shù)組(array)?
方法1
使用 Object.prototype.toString 來(lái)判斷是否是數(shù)組
function isArray(obj){ return Object.prototype.toString.call( obj ) === '[object Array]'; }
這里使用call來(lái)使 toString 中 this 指向 obj。進(jìn)而完成判斷
方法二
使用 原型鏈 來(lái)完成判斷
function isArray(obj){ return obj.__proto__ === Array.prototype; }
基本思想是利用 實(shí)例如果是某個(gè)構(gòu)造函數(shù)構(gòu)造出來(lái)的那么 它的 __proto__是指向構(gòu)造函數(shù)的 prototype屬性。
方法3
利用JQuery
function isArray(obj){ return $.isArray(obj) }
JQuery isArray 的實(shí)現(xiàn)其實(shí)就是方法1
問(wèn)題8:下面代碼輸出什么?
var output = (function(x){ delete x; return x; })(0); console.log(output);
輸出是 0。 delete 操作符是將object的屬性刪去的操作。但是這里的 x 是并不是對(duì)象的屬性, delete 操作符并不能作用。
問(wèn)題9:下面代碼輸出什么?
var x = 1; var output = (function(){ delete x; return x; })(); console.log(output);
輸出是 1。delete 操作符是將object的屬性刪去的操作。但是這里的 x 是并不是對(duì)象的屬性, delete 操作符并不能作用。
問(wèn)題10:下面代碼輸出什么?
var x = { foo : 1}; var output = (function(){ delete x.foo; return x.foo; })(); console.log(output);
輸出是 undefined。x雖然是全局變量,但是它是一個(gè)object。delete作用在x.foo上,成功的將x.foo刪去。所以返回undefined
問(wèn)題11:下面代碼輸出什么?
var Employee = { company: 'xyz' } var emp1 = Object.create(Employee); delete emp1.company console.log(emp1.company);
輸出是 xyz,這里的 emp1 通過(guò) prototype 繼承了 Employee的 company。emp1自己并沒(méi)有company屬性。所以delete操作符的作用是無(wú)效的。
問(wèn)題12:什么是 undefined x 1 ?
在chrome下執(zhí)行如下代碼,我們就可以看到undefined x 1的身影。
var trees = ["redwood","bay","cedar","oak","maple"]; delete trees[3]; console.log(trees);
當(dāng)我們使用 delete 操作符刪除一個(gè)數(shù)組中的元素,這個(gè)元素的位置就會(huì)變成一個(gè)占位符。打印出來(lái)就是undefined x 1。 注意如果我們使用trees[3] === 'undefined × 1'返回的是 false。因?yàn)樗鼉H僅是一種打印表示,并不是值變?yōu)閡ndefined x 1。
問(wèn)題13:下面代碼輸出什么?
var trees = ["xyz","xxxx","test","ryan","apple"]; delete trees[3]; console.log(trees.length);
輸出是5。因?yàn)閐elete操作符并不是影響數(shù)組的長(zhǎng)度。
問(wèn)題14:下面代碼輸出什么?
var bar = true; console.log(bar + 0); console.log(bar + "xyz"); console.log(bar + true); console.log(bar + false);
輸出是
1
truexyz
2
1
下面給出一個(gè)加法操作表
- Number + Number -> 加法
- Boolean + Number -> 加法
- Boolean + Boolean -> 加法
- Number + String -> 連接
- String + Boolean -> 連接
- String + String -> 連接
問(wèn)題15:下面代碼輸出什么?
var z = 1, y = z = typeof y; console.log(y);
輸出是 undefined。js中賦值操作結(jié)合律是右至左的 ,即從最右邊開(kāi)始計(jì)算值賦值給左邊的變量。
上面代碼等價(jià)于
var z = 1 z = typeof y; var y = z; console.log(y);
問(wèn)題16:下面代碼輸出什么?
var foo = function bar(){ return 12; }; typeof bar();
輸出是拋出異常,bar is not defined。 如果想讓代碼正常運(yùn)行,需要這樣修改代碼:
var bar = function(){ return 12; }; typeof bar();
或者是
function bar(){ return 12; }; typeof bar();
明確說(shuō)明這個(gè)下問(wèn)題
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
問(wèn)題17:兩種函數(shù)聲明有什么區(qū)別?
var foo = function(){ // Some code }; function bar(){ // Some code };
foo的定義是在運(yùn)行時(shí)。想系統(tǒng)說(shuō)明這個(gè)問(wèn)題,我們要引入變量提升的這一概念。
我們可以運(yùn)行下如下代碼看看結(jié)果。
console.log(foo) console.log(bar) var foo = function(){ // Some code }; function bar(){ // Some code };
輸出為
undefined function bar(){ // Some code };
為什么那?為什么 foo 打印出來(lái)是 undefined,而 bar打印出來(lái)卻是函數(shù)?
JavaScript在執(zhí)行時(shí),會(huì)將變量提升。
所以上面代碼JavaScript 引擎在實(shí)際執(zhí)行時(shí)按這個(gè)順序執(zhí)行。
// foo bar的定義位置被提升 function bar(){ // Some code }; var foo; console.log(foo) console.log(bar) foo = function(){ // Some code };
原代碼的輸出合理解釋了。
問(wèn)題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$
這題同樣考察的是變量提升。等價(jià)于以下代碼
var salary = "1000$"; (function () { var salary ; console.log("Original salary was " + salary); salary = "5000$"; console.log("My New Salary " + salary); })();
問(wèn)題19:什么是 instanceof 操作符?下面代碼輸出什么?
function foo(){ return foo; } console.log(new foo() instanceof foo);
instanceof操作符用來(lái)判斷是否當(dāng)前對(duì)象是特定類的對(duì)象。
如
function Animal(){ //或者不寫(xiě)return語(yǔ)句 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
問(wèn)題20: 如果我們使用JavaScript的"關(guān)聯(lián)數(shù)組",我們?cè)趺从?jì)算"關(guān)聯(lián)數(shù)組"的長(zhǎng)度?
var counterArray = { A : 3, B : 4 }; counterArray["C"] = 1;
其實(shí)答案很簡(jiǎn)單,直接計(jì)算key的數(shù)量就可以了。
Object.keys(counterArray).length // Output 3
本文給出的面試題答案只是很多合理答案中的幾個(gè),可能會(huì)不全面,歡迎大家補(bǔ)充。
由于個(gè)人疏忽等原因,本文中難免會(huì)存在少量錯(cuò)誤,歡迎大家批評(píng)指正。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
js判斷iframe內(nèi)的網(wǎng)頁(yè)是否滾動(dòng)到底部觸發(fā)事件
這篇文章主要介紹了js判斷iframe內(nèi)的網(wǎng)頁(yè)是否滾動(dòng)到底部觸發(fā)事件,需要的朋友可以參考下2014-03-03JavaScript學(xué)習(xí)筆記--常用的互動(dòng)方法
本文對(duì)JavaScript中常用的互動(dòng)方法進(jìn)行實(shí)例分析介紹,圖文并茂,有需要的朋友可以看下2016-12-12javascript實(shí)現(xiàn)繼承的簡(jiǎn)單實(shí)例
這篇文章主要介紹了javascript實(shí)現(xiàn)繼承的簡(jiǎn)單實(shí)例的相關(guān)資料,需要的朋友可以參考下2015-07-07HTML頁(yè)面滾動(dòng)時(shí)獲取離頁(yè)面頂部的距離2種實(shí)現(xiàn)方法
獲取離滾動(dòng)頁(yè)面的頂部距離有兩種方法一是DOM;而是jquery,具體的實(shí)現(xiàn)如下,感興趣的朋友可以嘗試操作下2013-09-09使用javascript實(shí)現(xiàn)頁(yè)面加載loading動(dòng)畫(huà)(附完整源碼)
由于項(xiàng)目中多處要給ajax提交的時(shí)候增加等待動(dòng)畫(huà)效果,所以就寫(xiě)了一個(gè)簡(jiǎn)單的通用js方法,這篇文章主要給大家介紹了關(guān)于如何使用javascript實(shí)現(xiàn)頁(yè)面加載loading動(dòng)畫(huà)的相關(guān)資料,需要的朋友可以參考下2024-06-06D3.js實(shí)現(xiàn)簡(jiǎn)潔實(shí)用的動(dòng)態(tài)儀表盤(pán)的示例
本篇文章主要介紹了D3.js實(shí)現(xiàn)簡(jiǎn)潔實(shí)用的動(dòng)態(tài)儀表盤(pán)的示例,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-04-04JavaScript實(shí)現(xiàn)全選和全不選操作
這篇文章主要為大家詳細(xì)介紹了JavaScript實(shí)現(xiàn)全選和全不選操作,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-09-09js實(shí)現(xiàn)簡(jiǎn)單的省市縣三級(jí)聯(lián)動(dòng)效果實(shí)例
這篇文章主要介紹了js實(shí)現(xiàn)簡(jiǎn)單的省市縣三級(jí)聯(lián)動(dòng)效果,以完整實(shí)例形式分析了JavaScript實(shí)現(xiàn)省市縣三級(jí)聯(lián)動(dòng)效果的具體步驟與相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下2016-02-02