問題1:JavaScript 中
undefined
和
not defined
的區別
JavaScript 未聲明變數直接使用會拋出異常:
var name is not defined
,如果沒有處理異常,代碼就停止運行了。
但是,使用
typeof undeclared_variable
並不會產生異常,會直接返回 。
varx;
// 聲明 xconsole.log(x);
//output: undefinedconsole.log(
typeofy);
//output: undefinedconsole.log(z);
// 拋出異常: ReferenceError: z is not defined問題2:下面的代碼輸出什麼?正確的答案應該是
1undefined
。JavaScript中if語句求值其實使用
eval
函數,
eval(function f{})
返回
function f{}
也就是 。
下面我們可以把代碼改造下,變成其等效代碼。
vark =
1;
if(
1) {
eval(
functionfoo{}); k +=
typeoffoo; }
console.log(k);上面的代碼輸出其實就是
1undefined
。為什麼那?我們查看下
eval
說明文檔即可獲得答案
該方法只接受原始字元串作為參數,如果 string 參數不是原始字元串,那麼該方法將不作任何改變地返回。
恰恰
function f{}
語句的返回值是
undefined
,所以一切都說通了。
注意上面代碼和以下代碼不同。
vark =
1;
if(
1) {
functionfoo{}; k +=
typeoffoo; }
console.log(k);
// output 1function問題3:在JavaScript中創建一個真正的private方法有什麼缺點?
每一個對象都會創建一個private方法的方法,這樣很耗費內存
觀察下面代碼
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);
varemp2 =
newEmployee(
"Merry""Pluto"2000);
varemp3 =
newEmployee(
"Ren""Pluto"2500);
在這裡 emp1,emp2,emp3都有一個increaseSalary私有方法的副本。
所以我們除非必要,非常不推薦使用私有方法。
問題4:JavaScript中什麼是
閉包?寫出一個例子
老生常談的問題了,閉包是在一個函數里聲明了另外一個函數,並且這個函數訪問了父函數作用域里的變數。
下面給出一個閉包例子,它訪問了三個域的變數
- 它自己作用域的變數
- 父函數作用域的變數
- 全局作用域的變數
globalVar =
"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 parameterinnerFunction is closure that is defined inside outerFunc
輸出很簡單:
outerArg=
7outerFuncVar= x
innerArg=
5innerFuncVar= y
globalVar= abc問題5:寫一個mul函數,使用方法如下。
console.log(mul(
2)(
3)(
4));
// output : 24 console.log(mul(
4)(
3)(
4));
// output : 48答案直接給出:
簡單說明下: mul 返回一個匿名函數,運行這個匿名函數又返回一個匿名函數,最裡面的匿名函數可以訪問 x,y,z 進而算出乘積返回即可。
對於JavaScript中的函數一般可以考察如下知識點:
- 函數是一等公民
- 函數可以有屬性,並且能連接到它的構造方法
- 函數可以像一個變數一樣存在內存中
- 函數可以當做參數傳給其他函數
- 函數可以返回其他函數
怎麼清空
arrayList
方法1
arrayList= ;
直接改變arrayList所指向的對象,原對象並不改變。
方法2
arrayList.length = 0;
這種方法通過設置length=0 使原數組清除元素。
方法3
arrayList.splice(0,
arrayList.length);
和方法2相似
問題7:怎麼判斷一個object是否是數組(array)?
方法1
使用 Object.prototype.toString 來判斷是否是數組
functionisArray(obj){
returnObject.prototype.toString.call( obj ) ===
'[object Array]'; }
這裡使用call來使 toString 中 this 指向 obj。進而完成判斷
方法二
使用 原型鏈 來完成判斷
functionisArray(obj){
returnobj.__proto__ ===
Array.prototype; }基本思想是利用 實例如果是某個構造函數構造出來的那麼 它的
__proto__
是指向構造函數的
prototype
屬性。
方法3
利用JQuery
functionisArray(obj){
return$.isArray(obj) }
JQuery isArray 的實現其實就是方法1
問題8:下面代碼輸出什麼?
varoutput = (
function(x){
deletex;
returnx; })(
0);
console.log(output);輸出是 。
delete
操作符是將object的屬性刪去的操作。但是這裡的
x
是並不是對象的屬性,
delete
操作符並不能作用。問題9:下面代碼輸出什麼?
varx =
1;
varoutput = (
function{
deletex;
returnx; });
console.log(output);
delete
x
是並不是對象的屬性,
delete
操作符並不能作用。問題10:下面代碼輸出什麼?
varx = { foo :
1};
varoutput = (
function{
deletex.foo;
returnx.foo; });
console.log(output);輸出是
undefined
。x雖然是全局變數,但是它是一個object。
delete
作用在
x.foo
上,成功的將
x.foo
刪去。所以返回
undefined
問題11:下面代碼輸出什麼?
varEmployee = { company:
'xyz'}
varemp1 =
Object.create(Employee);
deleteemp1.company
console.log(emp1.company);輸出是
xyz
,這裡的 emp1 通過 prototype 繼承了 Employee的 company。emp1自己並沒有company屬性。所以delete操作符的作用是無效的。問題12:什麼是 ?在chrome下執行如下代碼,我們就可以看到
undefined x 1
的身影。
vartrees = [
"redwood""bay""cedar""oak""maple"];
deletetrees[
3];
console.log(trees);當我們使用 delete 操作符刪除一個數組中的元素,這個元素的位置就會變成一個佔位符。列印出來就是
undefined x 1
。
注意如果我們使用
trees[3] === 'undefined × 1'
返回的是
false
。因為它僅僅是一種列印表示,並不是值變為
undefined x 1
。問題13:下面代碼輸出什麼?
vartrees = [
"xyz""xxxx""test""ryan""apple"];
deletetrees[
3];
console.log(trees.length);
輸出是5。因為delete操作符並不是影響數組的長度。
問題14:下面代碼輸出什麼?
varbar =
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 -> 連接
z =
1, y = z =
typeofy;
console.log(y);輸出是
undefined
。js中賦值操作結合律是右至左的 ,即從最右邊開始計算值賦值給左邊的變數。
上面代碼等價於
varz =
1z =
typeofy;
vary = z;
console.log(y);問題16:下面代碼輸出什麼?
varfoo =
functionbar{
return12; };
typeofbar;
輸出是拋出異常,bar is not defined。如果想讓代碼正常運行,需要這樣修改代碼:
varbar =
function{
return12; };
typeofbar;
或者是
functionbar{
return12; };
typeofbar;
明確說明這個下問題
varfoo =
functionbar{
// foo is visible here // bar is visible hereconsole.log(
typeofbar);
// Work here : )};
// bar is undefined here問題17:兩種函數聲明有什麼區別?
varfoo =
function{
// Some code};
functionbar{
// Some code};
foo的定義是在運行時。想系統說明這個問題,我們要引入變數提升的這一概念。
我們可以運行下如下代碼看看結果。
console.log(foo)
console.log(bar)
varfoo =
function{
// Some code};
functionbar{
// Some code};
輸出為
undefinedfunctionbar{
// Some code};
為什麼那?為什麼 foo 列印出來是 undefined,而 bar列印出來卻是函數?
JavaScript在執行時,會將變數提升。
所以上面代碼JavaScript 引擎在實際執行時按這個順序執行。
// foo bar的定義位置被提升functionbar{
// Some code};
varfoo;
console.log(foo)
console.log(bar) foo =
function{
// Some code};
原代碼的輸出合理解釋了。
問題18:下面代碼輸出什麼?
varsalary =
"1000$"; (
function{
console.log(
"Original salary was "+ salary);
varsalary =
"5000$";
console.log(
"My New Salary "+ salary); });
輸出是
Original salary was undefined My
NewSalary
5000$
這題同樣考察的是變數提升。等價於以下代碼
varsalary =
"1000$"; (
function{
varsalary ;
console.log(
"Original salary was "+ salary); salary =
"5000$";
console.log(
"My New Salary "+ salary); });
instanceof
操作符?下面代碼輸出什麼?
functionfoo{
returnfoo; }
console.log(
newfoo
instanceoffoo);
instanceof
操作符用來判斷是否當前對象是特定類的對象。
如
functionAnimal{
//或者不寫return語句returnthis; }
vardog =
newAnimal; dog
instanceofAnimal
// Output : true但是,這裡的foo定義為
functionfoo{
returnfoo; }
所以
// here bar is pointer to function foo{return foo}.varbar =
newfoo;所以
new foo instanceof foo
返回 false問題20: 如果我們使用JavaScript的」關聯數組」,我們怎麼計算」關聯數組」的長度?
varcounterArray = {
A:
3,
B:
4}; counterArray[
"C"] =
1;
其實答案很簡單,直接計算key的數量就可以了。
Object.keys(counterArray).length
// Output 3面試題參考自: 21 Essential JavaScript Interview Questions | Codementor
本文給出的面試題答案只是很多合理答案中的幾個,可能會不全面,歡迎大家補充。
由於個人疏忽等原因,本文中難免會存在少量錯誤,歡迎大家批評指正。