undefined
和 not defined
的區別JavaScript 未聲明變量直接使用會拋出異常:var name is not defined
,若是沒有處理異常,代碼就中止運行了。
可是,使用typeof undeclared_variable
並不會產生異常,會直接返回 undefined
。javascript
var x; // 聲明 x console.log(x); //output: undefined
console.log(typeof y); //output: undefined
console.log(z); // 拋出異常: ReferenceError: z is not defined
var y = 1; if (function f(){}) { y += typeof f; } console.log(y);
正確的答案應該是 1undefined
。java
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
每個對象都會建立一個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私有方法的副本。
因此咱們除非必要,很是不推薦使用私有方法。
老生常談的問題了,閉包是在一個函數裏聲明瞭另一個函數,而且這個函數訪問了父函數做用域裏的變量。
下面給出一個閉包例子,它訪問了三個域的變量
它本身做用域的變量
父函數做用域的變量
全局做用域的變量
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
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中的函數通常能夠考察以下知識點:
函數是一等公民
函數能夠有屬性,而且能鏈接到它的構造方法
函數能夠像一個變量同樣存在內存中
函數能夠當作參數傳給其餘函數
函數能夠返回其餘函數
如
var arrayList = ['a','b','c','d','e','f'];
怎麼清空 arrayList
arrayList = [];
直接改變arrayList所指向的對象,原對象並不改變。
arrayList.length = 0;
這種方法經過設置length=0 使原數組清除元素。
arrayList.splice(0, arrayList.length);
和方法2類似
使用 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
屬性。
利用JQuery
function isArray(obj){ return $.isArray(obj) }
JQuery isArray 的實現其實就是方法1
var output = (function(x){ delete x; return x; })(0); console.log(output);
輸出是 0
。 delete
操做符是將object的屬性刪去的操做。可是這裏的 x
是並非對象的屬性, delete
操做符並不能做用。
var x = 1; var output = (function(){ delete x; return x; })(); console.log(output);
輸出是 1
。delete
操做符是將object的屬性刪去的操做。可是這裏的 x
是並非對象的屬性, delete
操做符並不能做用。
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
var Employee = { company: 'xyz' } var emp1 = Object.create(Employee); delete emp1.company console.log(emp1.company);
輸出是 xyz
,這裏的 emp1 經過 prototype 繼承了 Employee的 company。emp1本身並無company屬性。因此delete操做符的做用是無效的。
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
。
var trees = ["xyz","xxxx","test","ryan","apple"]; delete trees[3]; console.log(trees.length);
輸出是5。由於delete操做符並非影響數組的長度。
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 -> 鏈接
var z = 1, y = z = typeof y; console.log(y);
輸出是 undefined
。js中賦值操做結合律是右至左的 ,即從最右邊開始計算值賦值給左邊的變量。
上面代碼等價於
var z = 1 z = typeof y; var y = z; console.log(y);
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
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 };
原代碼的輸出合理解釋了。
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); })();
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
var counterArray = { A : 3, B : 4 }; counterArray["C"] = 1;
其實答案很簡單,直接計算key的數量就能夠了。
Object.keys(counterArray).length // Output 3
面試題參考自: 21 Essential JavaScript Interview Questions | Codementor
本文給出的面試題答案只是不少合理答案中的幾個,可能會不全面,歡迎你們補充。
因爲我的疏忽等緣由,本文中不免會存在少許錯誤,歡迎你們批評指正。