問(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。
varx;// 聲明 xconsole.log(x);//output: undefined
console.log(typeof?y);?//output: undefined
console.log(z);?// 拋出異常: ReferenceError: z is not defined
問(wèn)題2:下面的代碼輸出什么叛赚?
vary =1;if(functionf(){}) {? ? y +=typeoff;}console.log(y);
正確的答案應(yīng)該是?1undefined澡绩。
JavaScript中if語(yǔ)句求值其實(shí)使用eval函數(shù)稽揭,eval(function f(){})?返回?function f(){}?也就是?true。
下面我們可以把代碼改造下英古,變成其等效代碼淀衣。
vark =1;if(1) {eval(functionfoo(){});? ? k +=typeoffoo;}console.log(k);
上面的代碼輸出其實(shí)就是?1undefined。為什么那召调?我們查看下?eval()?說(shuō)明文檔即可獲得答案
該方法只接受原始字符串作為參數(shù)膨桥,如果 string 參數(shù)不是原始字符串,那么該方法將不作任何改變地返回唠叛。
恰恰?function f(){}?語(yǔ)句的返回值是?undefined只嚣,所以一切都說(shuō)通了。
注意上面代碼和以下代碼不同艺沼。
vark =1;if(1) {functionfoo(){};? ? k +=typeoffoo;}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)存
觀察下面代碼
varEmployee =function(name, company, salary){this.name = name ||"";this.company = company ||"";this.salary = salary ||5000;// Private methodvarincreaseSalary =function(){this.salary =this.salary +1000;? ? };// Public methodthis.dispalyIncreasedSalary =function(){? ? ? ? increaseSlary();console.log(this.salary);? ? };};// Create Employee class objectvaremp1 =newEmployee("John","Pluto",3000);// Create Employee class objectvaremp2 =newEmployee("Merry","Pluto",2000);// Create Employee class objectvaremp3 =newEmployee("Ren","Pluto",2500);
在這里 emp1,emp2,emp3都有一個(gè)increaseSalary私有方法的副本障般。
所以我們除非必要调鲸,非常不推薦使用私有方法。
問(wèn)題4:JavaScript中什么是閉包挽荡?寫出一個(gè)例子
老生常談的問(wèn)題了藐石,閉包是在一個(gè)函數(shù)里聲明了另外一個(gè)函數(shù),并且這個(gè)函數(shù)訪問(wèn)了父函數(shù)作用域里的變量定拟。
下面給出一個(gè)閉包例子于微,它訪問(wèn)了三個(gè)域的變量
它自己作用域的變量
父函數(shù)作用域的變量
全局作用域的變量
varglobalVar ="abc";// Parent self invoking function (functionouterFunction(outerArg){// begin of scope outerFunction// Variable declared in outerFunction function scope varouterFuncVar ='x';// Closure self-invoking function (functioninnerFunction(innerArg){// begin of scope innerFunction// variable declared in innerFunction function scopevarinnerFuncVar ="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=7outerFuncVar= xinnerArg=5innerFuncVar= yglobalVar= abc
問(wèn)題5:寫一個(gè)mul函數(shù),使用方法如下青自。
console.log(mul(2)(3)(4));// output : 24 console.log(mul(4)(3)(4));// output : 48
答案直接給出:
functionmul(x){returnfunction(y){// anonymous function returnfunction(z){// anonymous function returnx * 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ù)組
functionisArray(obj){returnObject.prototype.toString.call( obj ) ==='[object Array]';}
這里使用call來(lái)使 toString 中 this 指向 obj商源。進(jìn)而完成判斷
方法二
使用 原型鏈 來(lái)完成判斷
functionisArray(obj){returnobj.__proto__ ===Array.prototype;}
基本思想是利用 實(shí)例如果是某個(gè)構(gòu)造函數(shù)構(gòu)造出來(lái)的那么 它的?__proto__是指向構(gòu)造函數(shù)的?prototype屬性。
方法3
利用JQuery
functionisArray(obj){return$.isArray(obj)}
JQuery isArray 的實(shí)現(xiàn)其實(shí)就是方法1
問(wèn)題8:下面代碼輸出什么谋减?
varoutput = (function(x){deletex;returnx;})(0);console.log(output);
輸出是?0牡彻。?delete?操作符是將object的屬性刪去的操作。但是這里的?x?是并不是對(duì)象的屬性,?delete?操作符并不能作用庄吼。
問(wèn)題9:下面代碼輸出什么缎除?
varx =1;varoutput = (function(){deletex;returnx;})();console.log(output);
輸出是?1。delete?操作符是將object的屬性刪去的操作总寻。但是這里的?x?是并不是對(duì)象的屬性器罐,?delete?操作符并不能作用。
問(wèn)題10:下面代碼輸出什么渐行?
varx = {foo:1};varoutput = (function(){deletex.foo;returnx.foo;})();console.log(output);
輸出是?undefined轰坊。x雖然是全局變量,但是它是一個(gè)object祟印。delete作用在x.foo上肴沫,成功的將x.foo刪去。所以返回undefined
問(wèn)題11:下面代碼輸出什么蕴忆?
varEmployee = {company:'xyz'}varemp1 =Object.create(Employee);deleteemp1.companyconsole.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的身影沉衣。
vartrees = ["redwood","bay","cedar","oak","maple"];deletetrees[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:下面代碼輸出什么既荚?
vartrees = ["xyz","xxxx","test","ryan","apple"];deletetrees[3];console.log(trees.length);
輸出是5稚失。因?yàn)閐elete操作符并不是影響數(shù)組的長(zhǎng)度。
問(wèn)題14:下面代碼輸出什么恰聘?
varbar =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:下面代碼輸出什么句各?
varz =1, y = z =typeofy;console.log(y);
輸出是?undefined。js中賦值操作結(jié)合律是右至左的 晴叨,即從最右邊開(kāi)始計(jì)算值賦值給左邊的變量凿宾。
上面代碼等價(jià)于
varz =1z =typeofy;vary = z;console.log(y);
問(wèn)題16:下面代碼輸出什么?
varfoo =functionbar(){return12; };typeofbar();
輸出是拋出異常兼蕊,bar is not defined初厚。
如果想讓代碼正常運(yùn)行,需要這樣修改代碼:
varbar =function(){return12; };typeofbar();
或者是
functionbar(){return12; };typeofbar();
明確說(shuō)明這個(gè)下問(wèn)題
varfoo =functionbar(){// foo is visible here // bar is visible hereconsole.log(typeofbar());// Work here :)};// foo is visible here// bar is undefined here
問(wèn)題17:兩種函數(shù)聲明有什么區(qū)別孙技?
varfoo =function(){// Some code};functionbar(){// Some code};
foo的定義是在運(yùn)行時(shí)产禾。想系統(tǒng)說(shuō)明這個(gè)問(wèn)題排作,我們要引入變量提升的這一概念。
我們可以運(yùn)行下如下代碼看看結(jié)果亚情。
console.log(foo)console.log(bar)varfoo =function(){// Some code};functionbar(){// Some code};
輸出為
undefinedfunctionbar(){// Some code};
為什么那妄痪?為什么 foo 打印出來(lái)是 undefined,而 bar打印出來(lái)卻是函數(shù)楞件?
JavaScript在執(zhí)行時(shí)衫生,會(huì)將變量提升。
所以上面代碼JavaScript 引擎在實(shí)際執(zhí)行時(shí)按這個(gè)順序執(zhí)行履因。
// foo bar的定義位置被提升functionbar(){// Some code};varfoo;console.log(foo)console.log(bar)foo =function(){// Some code};
原代碼的輸出合理解釋了障簿。
問(wèn)題18:下面代碼輸出什么?
varsalary ="1000$";(function(){console.log("Original salary was "+ salary);varsalary ="5000$";console.log("My New Salary "+ salary);})();
輸出是
Originalsalary was undefinedMyNew Salary 5000$
這題同樣考察的是變量提升栅迄。等價(jià)于以下代碼
varsalary ="1000$"; (function(){varsalary ;console.log("Original salary was "+ salary);? ? salary ="5000$";console.log("My New Salary "+ salary); })();
問(wèn)題19:什么是?instanceof?操作符站故?下面代碼輸出什么?
functionfoo(){returnfoo; }console.log(newfoo()instanceoffoo);
instanceof操作符用來(lái)判斷是否當(dāng)前對(duì)象是特定類的對(duì)象毅舆。
如
functionAnimal(){//或者不寫return語(yǔ)句returnthis;}vardog =newAnimal();doginstanceofAnimal// Output : true
但是西篓,這里的foo定義為
functionfoo(){returnfoo; }
所以
// here bar is pointer to function foo(){return foo}.varbar =newfoo();
所以?new foo() instanceof foo?返回 false
問(wèn)題20: 如果我們使用JavaScript的"關(guān)聯(lián)數(shù)組",我們?cè)趺从?jì)算"關(guān)聯(lián)數(shù)組"的長(zhǎng)度憋活?
varcounterArray = {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)指正。