1、請解釋 JavaScript 中 this 是如何工做的。javascript
首先:this 永遠指向函數運行時所在的對象,而不是函數被建立時所在的對象。匿名函數或不處於任何對象中的函數指向 window 。java
一、 方法調用模式 chrome
當函數被保存爲對象的一個屬性時,成該函數爲該對象的方法。函數中this的值爲該對象。express
var foo = { name: 'fooname', getName: function (){ return this.name } } foo.getName(); // this => foo
二、 函數調用模式 編程
當函數並非對象的屬性。函數中this的值爲全局對象
note:某個方法中的內部函數中的this的值也是全局對象,而非外部函數的thisjson
function foo(){ this.name = 'fooname'; } foo(); // this => window
三、構造器調用模式 跨域
即便用new調用的函數,則其中this將會被綁定到那個新構造的對象。數組
function Foo(){ this.name = 'fooname'; } var foo = new Foo(); // this => foo
四、使用apply或call調用模式 瀏覽器
該模式調用時,函數中this被綁定到apply或call方法調用時接受的第一個參數。安全
function getName(name){ this.name = name; } var foo = {}; getName.call(foo, name); // this =>foo
改變this的值主要方法(目前想到的,歡迎評論添加):
apply或call方法調用時強制修改,使this指向第一個參數。
使用Function.bind方法創造新的函數,該新函數的中this指向所提供的第一個參數。
2、請解釋原型繼承 (prototypal inheritance) 的原理。
JavaScript沒有「子類」和「父類」的概念,也沒有「類」(class)和「實例」(instance)的區分,全靠「原型鏈」(prototype chain)模式,來實現繼承。
每一個函數Sub都有一個屬性prototype,prototype指向一個原型對象,原型對象中也有一個指向函數的屬性constructor,經過new一個函數Sub能夠產生實例instance,調用這個instance的某個屬性或方法時,instance會先查找自身是否有這個方法或者屬性,沒有的話就會去實例的構造函數Sub的原型prototype中查找,即Sub.prototype,若是給原型對象Sub.prototype賦予另外一個類型的實例superInstance,則是在superInstance中查找的,這個superInstance中也有屬性prototype指向某個原型對象,以此一級級往上最終到Object.prototype,這樣就造成了原型繼承。
利用此原理能夠本身實現一個inherits函數:
function inherits(subType, superType){ var _prototype = Object.create(superType.prototype); _prototype.constructor = subType; subType.prototype = _prototype; }
3、解釋爲何接下來這段代碼不是 IIFE (當即調用的函數表達式):function foo(){ }(); 要作哪些改動使它變成 IIFE?
(function fn(){..})()
,函數被包含在一個括號內,變成爲一個表達式,隨後跟着一個(),就當即執行這個函數。
IIFE的一些做用:
4、(function fn(){..})(),函數被包含在一個括號內,變成爲一個表達式,隨後跟着一個(),就當即執行這個函數。
IIFE的一些做用:
當某個函數調用時會建立一個執行環境以及做用域鏈,而後根據arguments和其它命名參數初始化造成活動對象。在外部函數調用結束後,其執行環境與做用域鏈被銷燬,可是其活動對象保存在了閉包之中,最後在閉包函數調用結束後才銷燬。簡單的說,閉包就是可以讀取其餘函數內部變量的函數。在js中,閉包是指有權訪問另外一個函數做用域中的變量的函數。
如何使用:將A函數內部的B函數做爲A函數的返回值返回。
爲何要:
一、匿名自執行函數
有的場景下函數只須要執行一次,例如init()之類的函數,其內部變量無需維護,咱們可使用閉包。 咱們建立了一個匿名的函數,並當即執行它,因爲外部沒法引用它內部的變量,所以在函數執行完後會馬上釋放資源,並且不污染全局對象。
二、封裝
模擬面向對象的代碼風格進行封裝,使私有屬性存在成爲可能。
5、.call 和 .apply 的區別是什麼?
.call和.apply的共同點是都是用來改變函數體內this對象的值。
區別是第二個參數不同。apply()的第二個參數是一個類數組對象arguments,參數都是以數組的形式傳入,而call(),傳遞給他的是一系列參數。例如
Math.max.call(null, 1, 2, 3, 4); //4 Math.max.apply(null, [1, 2, 3, 4]); //4
6、請解釋 Function.prototype.bind?
Function.prototype.bind方法會建立一個新函數,當這個新函數被調用時,它的this值是傳遞給bind()的第一個參數, 它的參數是bind()的其餘參數和其本來的參數.
7、請指出 JavaScript 宿主對象 (host objects) 和原生對象 (native objects) 的區別?
宿主對象是指DOM和BOM。
原生對象是Object、Function、Array、String、Boolean、Number、Date、RegExp、Error、Math等對象。
8、請指出如下代碼的區別:function Person(){}、var person = Person()、var person = new Person()?
function Person(){}
聲明一個函數Person()。
var person = Person()
將函數Person()的結果返回給變量person,若是沒有返回值則person爲undefined。
var person = new Person()
new一個Person的實例對象。
9、請儘量詳盡的解釋 Ajax 的工做原理。以及使用 Ajax 都有哪些優劣?
Ajax是無需刷新頁面就能從服務器取得數據的一種方法。
Ajax經過XmlHttpRequest對象來向服務器發異步請求,從服務器得到數據,而後用javascript來操做DOM更新頁面。
過程
缺點
10、請解釋變量聲明提高 (hoisting)。
變量的聲明前置就是把變量的聲明提高到當前做用域的最前面。
函數的聲明前置就是把整個函數提高到當前做用域的最前面(位於前置的變量聲明後面)。
//變量的聲明前置 console.log(num);//undefined var num = 1; 等價於 //變量的聲明前置 var num; console.log(num);//undefined num = 1;
11、請描述事件冒泡機制 (event bubbling)。
事件冒泡(event bubbling),事件最開始時由觸發的那個元素身上發生,而後沿着DOM樹向上傳播,直到document對象。若是想阻止事件起泡,可使用e.stopPropagation()。
12、什麼是 「use strict」; ? 使用它的好處和壞處分別是什麼?
優勢
消除Javascript語法的一些不嚴謹之處,減小一些怪異行爲;
消除代碼運行的一些不安全之處,保證代碼運行的安全;
提升編譯器效率,增長運行速度;
爲將來新版本的Javascript作好鋪墊。
缺點
嚴格模式改變了語義。依賴這些改變可能會致使沒有實現嚴格模式的瀏覽器中出現問題或者錯誤。
十3、請解釋 JavaScript 的同源策略 (same-origin policy)。
同源策略限制了一個源(origin)中加載文本或腳本與來自其它源(origin)中資源的交互方式。同源指的是協議、域名、端口相同,同源策略是一種安全協議。
十4、請解釋 JSONP 的工做原理,以及它爲何不是真正的 Ajax。
JSONP(JSON with Padding)是一種非官方跨域數據交互協議,它容許在服務器端集成< script >標籤返回至客戶端,經過javascript回調的形式實現跨域訪問。
由於同源策略的緣由,咱們不能使用XMLHttpRequest與外部服務器進行通訊,可是< script >能夠訪問外部資源,因此經過JSON與< script >相結合的辦法,能夠繞過同源策略從外部服務器直接取得可執行的JavaScript函數。
原理
客戶端定義一個函數,好比jsonpCallback,而後建立< script >,src爲url + ?jsonp=jsonpCallback這樣的形式,以後服務器會生成一個和傳遞過來jsonpCallback同樣名字的參數,並把須要傳遞的數據當作參數傳入,好比jsonpCallback(json),而後返回給客戶端,此時客戶端就執行了這個服務器端返回的jsonpCallback(json)回調。
通俗的說,就是客戶端定義一個函數而後請求,服務器端返回的javascript內容就是調用這個函數,須要的數據都當作參數傳入這個函數了。
優勢 - 兼容性好,簡單易用,支持瀏覽器與服務器雙向通訊
缺點 - 只支持GET請求;存在腳本注入以及跨站請求僞造等安全問題
補充一點,JSONP不使用XMLHttpRequest對象加載資源,不屬於真正意義上的AJAX。
十5、== 和 === 有什麼不一樣?
通俗的說就是===比==要更爲嚴格,===比較過程當中沒有任何的類型轉換。
十6、什麼是三元表達式 (Ternary expression)?「三元 (Ternary)」 表示什麼意思?
如名字表示的三元運算符須要三個操做數。
語法是
條件 ? 結果1 : 結果2;
這裏你把條件寫在問號(?)的前面後面跟着用冒號(:)分隔的結果1和結果2。知足條件時結果1不然結果2。
十7、你怎麼看 AMD vs. CommonJS?
瀏覽器端異步和服務器端同步的模塊化編程規範
十8、請舉出一個匿名函數的典型用例?
定義回調函數,當即執行函數,做爲返回值的函數,使用方法var foo = function() {}定義的函數。
十9、描述如下變量的區別:null,undefined 或 undeclared?該如何檢測它們?
未定義的屬性、定義未賦值的爲undefined,JavaScript訪問不會報錯;null是一種特殊的object;NaN是一種特殊的number;undeclared 是未聲明也未賦值的變量,JavaScript訪問會報錯。
二10、在何時你會使用 document.write()?
DOM方法,可向文檔寫入 HTML 表達式或 JavaScript 代碼。
二11、如何實現下列代碼:[1,2,3,4,5].duplicator(); // [1,2,3,4,5,1,2,3,4,5]
Array.prototype.duplicator = function(){ var l = this.length,i; for(i=0;i<l;i++){ this.push(this[i]) } }
二12、解釋 function foo() {} 與 var foo = function() {} 用法的區別
函數聲明的兩種方法:
這種方式是聲明瞭個變量,而這個變量是個方法,變量在js中是能夠改變的。
也:將一個匿名函數賦值給了變量。
這種方式是聲明瞭個方法,foo這個名字沒法改變
二十3、請解釋可變 (mutable) 和不變 (immutable) 對象的區別。
在 JavaScript 中,對象是引用類型的數據,其優勢在於頻繁的修改對象時都是在原對象的基礎上修改,並不須要從新建立,這樣能夠有效的利用內存,不會形成內存空間的浪費,對象的這種特性能夠稱之爲 Mutable,中文的字面意思是「可變」。
Immutable 從字面上翻譯成中文是「不可變」。每次修改一個 Immutable 對象時都會建立一個新的不可變的對象,在新對象上操做並不會影響到原對象的數據。
二十4、使用 Promises 而非回調 (callbacks) 優缺點是什麼?
Promise是異步編程的一種解決方案,比傳統的解決方案——回調函數和事件——更合理和更強大。它由社區最先提出和實現,ES6將其寫進了語言標準,統一了用法,原生提供了Promise對象。
所謂Promise,簡單說就是一個容器,裏面保存着某個將來纔會結束的事件(一般是一個異步操做)的結果。從語法上說,Promise是一個對象,從它能夠獲取異步操做的消息。Promise提供統一的API,各類異步操做均可以用一樣的方法進行處理。
有了Promise對象,就能夠將異步操做以同步操做的流程表達出來,避免了層層嵌套的回調函數。此外,Promise對象提供統一的接口,使得控制異步操做更加容易。
Promise也有一些缺點。
首先,沒法取消Promise,一旦新建它就會當即執行,沒法中途取消。
其次,若是不設置回調函數,Promise內部拋出的錯誤,不會反應到外部。
第三,當處於Pending狀態時,沒法得知目前進展到哪個階段(剛剛開始仍是即將完成)。
二十5、請解釋同步 (synchronous) 和異步 (asynchronous) 函數的區別。
同步調用,在發起一個函數或方法調用時,沒有獲得結果以前,該調用就不返回,直到返回結果;
異步調用的概念和同步相對,在一個異步調用發起後,被調用者當即返回給調用者,但調用者不能馬上獲得結果,被調用者在實際處理這個調用的請求完成後,經過狀態、通知或回調等方式來通知調用者請求處理的結果。
簡單地說,同步就是發出一個請求後什麼事都不作,一直等待請求返回後纔會繼續作事;異步就是發出請求後繼續去作其餘事,這個請求處理完成後會通知你,這時候就能夠處理這個迴應了。
二十6、你使用哪些工具和技術來調試 JavaScript 代碼?
1.javascript的debugger語句
須要調試js的時候,咱們能夠給須要調試的地方經過debugger打斷點,代碼執行到斷點就會暫定,這時候經過單步調試等方式就能夠調試js代碼
if (waldo) { debugger; }
這時候打開console面板,就能夠調試了
2.DOM斷點
DOM斷點是一個Firebug和chrome DevTools提供的功能,當js須要操做打了斷點的DOM時,會自動暫停,相似debugger調試。
使用DOM斷點步驟:
選擇你要打斷點的DOM節點
右鍵選擇Break on..
選擇斷點類型
另外的調試方法例如alert, console.log,查看元素等就再也不贅述了。
二十7、你會使用怎樣的語言結構來遍歷對象屬性 (object properties) 和數組內容?
for in 語句 通常for循環 數組forEach方法