溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

分享JavaScript常見(jiàn)面試題

發(fā)布時(shí)間:2021-11-06 16:33:05 來(lái)源:億速云 閱讀:122 作者:iii 欄目:web開發(fā)

這篇文章主要講解了“分享JavaScript常見(jiàn)面試題”,文中的講解內(nèi)容簡(jiǎn)單清晰,易于學(xué)習(xí)與理解,下面請(qǐng)大家跟著小編的思路慢慢深入,一起來(lái)研究和學(xué)習(xí)“分享JavaScript常見(jiàn)面試題”吧!

一、請(qǐng)解釋 JavaScript 中 this 是如何工作的。

首先:this 永遠(yuǎn)指向函數(shù)運(yùn)行時(shí)所在的對(duì)象,而不是函數(shù)被創(chuàng)建時(shí)所在的對(duì)象。匿名函數(shù)或不處于任何對(duì)象中的函數(shù)指向 window 。

1、 方法調(diào)用模式

當(dāng)函數(shù)被保存為對(duì)象的一個(gè)屬性時(shí),成該函數(shù)為該對(duì)象的方法。函數(shù)中this的值為該對(duì)象。

var foo = {
    name: 'fooname',
    getName: function (){
        return this.name  
    }
}
foo.getName();  // this => foo

2、 函數(shù)調(diào)用模式

當(dāng)函數(shù)并不是對(duì)象的屬性。函數(shù)中this的值為全局對(duì)象
note:某個(gè)方法中的內(nèi)部函數(shù)中的this的值也是全局對(duì)象,而非外部函數(shù)的this

function foo(){
    this.name = 'fooname';  
}
foo();  // this => window

3、構(gòu)造器調(diào)用模式

即使用new調(diào)用的函數(shù),則其中this將會(huì)被綁定到那個(gè)新構(gòu)造的對(duì)象。

function Foo(){
    this.name = 'fooname';
}
var foo = new Foo();  // this => foo

4、使用apply或call調(diào)用模式

該模式調(diào)用時(shí),函數(shù)中this被綁定到apply或call方法調(diào)用時(shí)接受的第一個(gè)參數(shù)。

function getName(name){
    this.name = name;
}
var foo = {};
getName.call(foo, name);  // this =>foo

改變this的值主要方法(目前想到的,歡迎評(píng)論添加):
apply或call方法調(diào)用時(shí)強(qiáng)制修改,使this指向第一個(gè)參數(shù)。
使用Function.bind方法創(chuàng)造新的函數(shù),該新函數(shù)的中this指向所提供的第一個(gè)參數(shù)。

二、請(qǐng)解釋原型繼承 (prototypal inheritance) 的原理。

JavaScript沒(méi)有“子類”和“父類”的概念,也沒(méi)有“類”(class)和“實(shí)例”(instance)的區(qū)分,全靠“原型鏈”(prototype chain)模式,來(lái)實(shí)現(xiàn)繼承。

每個(gè)函數(shù)Sub都有一個(gè)屬性prototype,prototype指向一個(gè)原型對(duì)象,原型對(duì)象中也有一個(gè)指向函數(shù)的屬性constructor,通過(guò)new一個(gè)函數(shù)Sub可以產(chǎn)生實(shí)例instance,調(diào)用這個(gè)instance的某個(gè)屬性或方法時(shí),instance會(huì)先查找自身是否有這個(gè)方法或者屬性,沒(méi)有的話就會(huì)去實(shí)例的構(gòu)造函數(shù)Sub的原型prototype中查找,即Sub.prototype,如果給原型對(duì)象Sub.prototype賦予另一個(gè)類型的實(shí)例superInstance,則是在superInstance中查找的,這個(gè)superInstance中也有屬性prototype指向某個(gè)原型對(duì)象,以此一級(jí)級(jí)往上最終到Object.prototype,這樣就形成了原型繼承。

利用此原理可以自己實(shí)現(xiàn)一個(gè)inherits函數(shù):

function inherits(subType, superType){
    var _prototype = Object.create(superType.prototype);
    _prototype.constructor = subType;
    subType.prototype = _prototype;
}

三、解釋為什么接下來(lái)這段代碼不是 IIFE (立即調(diào)用的函數(shù)表達(dá)式):function foo(){ }(); 要做哪些改動(dòng)使它變成 IIFE?

(function fn(){..})(),函數(shù)被包含在一個(gè)括號(hào)內(nèi),變成為一個(gè)表達(dá)式,隨后跟著一個(gè)(),就立即執(zhí)行這個(gè)函數(shù)。

IIFE的一些作用:

  1. 創(chuàng)建作用域,內(nèi)部保存一些大量臨時(shí)變量的代碼防止命名沖突。

  2. 一些庫(kù)的外層用這種形式包起來(lái)防止作用域污染。

  3. 運(yùn)行一些只執(zhí)行一次的代碼。

四、(function fn(){..})(),函數(shù)被包含在一個(gè)括號(hào)內(nèi),變成為一個(gè)表達(dá)式,隨后跟著一個(gè)(),就立即執(zhí)行這個(gè)函數(shù)。

IIFE的一些作用:

  1. 創(chuàng)建作用域,內(nèi)部保存一些大量臨時(shí)變量的代碼防止命名沖突。

  2. 一些庫(kù)的外層用這種形式包起來(lái)防止作用域污染。

  3. 運(yùn)行一些只執(zhí)行一次的代碼。

當(dāng)某個(gè)函數(shù)調(diào)用時(shí)會(huì)創(chuàng)建一個(gè)執(zhí)行環(huán)境以及作用域鏈,然后根據(jù)arguments和其它命名參數(shù)初始化形成活動(dòng)對(duì)象。在外部函數(shù)調(diào)用結(jié)束后,其執(zhí)行環(huán)境與作用域鏈被銷毀,但是其活動(dòng)對(duì)象保存在了閉包之中,最后在閉包函數(shù)調(diào)用結(jié)束后才銷毀。簡(jiǎn)單的說(shuō),閉包就是能夠讀取其他函數(shù)內(nèi)部變量的函數(shù)。在js中,閉包是指有權(quán)訪問(wèn)另一個(gè)函數(shù)作用域中的變量的函數(shù)。

如何使用:將A函數(shù)內(nèi)部的B函數(shù)作為A函數(shù)的返回值返回。

為什么要:

1、匿名自執(zhí)行函數(shù)

有的場(chǎng)景下函數(shù)只需要執(zhí)行一次,例如init()之類的函數(shù),其內(nèi)部變量無(wú)需維護(hù),我們可以使用閉包。 我們創(chuàng)建了一個(gè)匿名的函數(shù),并立即執(zhí)行它,由于外部無(wú)法引用它內(nèi)部的變量,因此在函數(shù)執(zhí)行完后會(huì)立刻釋放資源,而且不污染全局對(duì)象。

2、封裝

模擬面向?qū)ο蟮拇a風(fēng)格進(jìn)行封裝,使私有屬性存在成為可能。

五、.call 和 .apply 的區(qū)別是什么?

.call和.apply的共同點(diǎn)是都是用來(lái)改變函數(shù)體內(nèi)this對(duì)象的值。

區(qū)別是第二個(gè)參數(shù)不一樣。apply()的第二個(gè)參數(shù)是一個(gè)類數(shù)組對(duì)象arguments,參數(shù)都是以數(shù)組的形式傳入,而call(),傳遞給他的是一系列參數(shù)。例如

Math.max.call(null, 1, 2, 3, 4);
//4
Math.max.apply(null, [1, 2, 3, 4]);
//4

六、請(qǐng)解釋 Function.prototype.bind?

Function.prototype.bind方法會(huì)創(chuàng)建一個(gè)新函數(shù),當(dāng)這個(gè)新函數(shù)被調(diào)用時(shí),它的this值是傳遞給bind()的第一個(gè)參數(shù), 它的參數(shù)是bind()的其他參數(shù)和其原本的參數(shù).

七、請(qǐng)指出 JavaScript 宿主對(duì)象 (host objects) 和原生對(duì)象 (native objects) 的區(qū)別?

宿主對(duì)象是指DOM和BOM。
原生對(duì)象是Object、Function、Array、String、Boolean、Number、Date、RegExp、Error、Math等對(duì)象。

八、請(qǐng)指出以下代碼的區(qū)別:function Person(){}、var person = Person()、var person = new Person()?

function Person(){}

聲明一個(gè)函數(shù)Person()。

var person = Person()

將函數(shù)Person()的結(jié)果返回給變量person,如果沒(méi)有返回值則person為undefined。

var person = new Person()

new一個(gè)Person的實(shí)例對(duì)象。

九、請(qǐng)盡可能詳盡的解釋 Ajax 的工作原理。以及使用 Ajax 都有哪些優(yōu)劣?

Ajax是無(wú)需刷新頁(yè)面就能從服務(wù)器取得數(shù)據(jù)的一種方法。

Ajax通過(guò)XmlHttpRequest對(duì)象來(lái)向服務(wù)器發(fā)異步請(qǐng)求,從服務(wù)器獲得數(shù)據(jù),然后用javascript來(lái)操作DOM更新頁(yè)面。

過(guò)程

  1. 創(chuàng)建XMLHttpRequest對(duì)象。

  2. 設(shè)置響應(yīng)HTTP請(qǐng)求的回調(diào)函數(shù)。

  3. 創(chuàng)建一個(gè)HTTP請(qǐng)求,指定相應(yīng)的請(qǐng)求方法、url等。

  4. 發(fā)送HTTP請(qǐng)求。

  5. 獲取服務(wù)器端返回的數(shù)據(jù)。

  6. 使用JavaScript操作DOM更新頁(yè)面。

缺點(diǎn)

  1. 對(duì)搜索引擎不友好

  2. 要實(shí)現(xiàn)Ajax下的前后退功能成本較大

  3. 跨域問(wèn)題限制

十、請(qǐng)解釋變量聲明提升 (hoisting)。

變量的聲明前置就是把變量的聲明提升到當(dāng)前作用域的最前面。
函數(shù)的聲明前置就是把整個(gè)函數(shù)提升到當(dāng)前作用域的最前面(位于前置的變量聲明后面)。

//變量的聲明前置
console.log(num);//undefined
var num = 1;
等價(jià)于
//變量的聲明前置
var num;
console.log(num);//undefined
num = 1;

十一、請(qǐng)描述事件冒泡機(jī)制 (event bubbling)。

事件冒泡(event bubbling),事件最開始時(shí)由觸發(fā)的那個(gè)元素身上發(fā)生,然后沿著DOM樹向上傳播,直到document對(duì)象。如果想阻止事件起泡,可以使用e.stopPropagation()。

十二、什么是 “use strict”; ? 使用它的好處和壞處分別是什么?

優(yōu)點(diǎn)

消除Javascript語(yǔ)法的一些不嚴(yán)謹(jǐn)之處,減少一些怪異行為;
消除代碼運(yùn)行的一些不安全之處,保證代碼運(yùn)行的安全;
提高編譯器效率,增加運(yùn)行速度;
為未來(lái)新版本的Javascript做好鋪墊。

缺點(diǎn)

嚴(yán)格模式改變了語(yǔ)義。依賴這些改變可能會(huì)導(dǎo)致沒(méi)有實(shí)現(xiàn)嚴(yán)格模式的瀏覽器中出現(xiàn)問(wèn)題或者錯(cuò)誤。

十三、請(qǐng)解釋 JavaScript 的同源策略 (same-origin policy)。

同源策略限制了一個(gè)源(origin)中加載文本或腳本與來(lái)自其它源(origin)中資源的交互方式。同源指的是協(xié)議、域名、端口相同,同源策略是一種安全協(xié)議。

十四、請(qǐng)解釋 JSONP 的工作原理,以及它為什么不是真正的 Ajax。

JSONP(JSON with Padding)是一種非官方跨域數(shù)據(jù)交互協(xié)議,它允許在服務(wù)器端集成< script >標(biāo)簽返回至客戶端,通過(guò)javascript回調(diào)的形式實(shí)現(xiàn)跨域訪問(wèn)。

因?yàn)橥床呗缘脑?,我們不能使用XMLHttpRequest與外部服務(wù)器進(jìn)行通信,但是< script >可以訪問(wèn)外部資源,所以通過(guò)JSON與< script >相結(jié)合的辦法,可以繞過(guò)同源策略從外部服務(wù)器直接取得可執(zhí)行的JavaScript函數(shù)。

原理

客戶端定義一個(gè)函數(shù),比如jsonpCallback,然后創(chuàng)建< script >,src為url + ?jsonp=jsonpCallback這樣的形式,之后服務(wù)器會(huì)生成一個(gè)和傳遞過(guò)來(lái)jsonpCallback一樣名字的參數(shù),并把需要傳遞的數(shù)據(jù)當(dāng)做參數(shù)傳入,比如jsonpCallback(json),然后返回給客戶端,此時(shí)客戶端就執(zhí)行了這個(gè)服務(wù)器端返回的jsonpCallback(json)回調(diào)。

通俗的說(shuō),就是客戶端定義一個(gè)函數(shù)然后請(qǐng)求,服務(wù)器端返回的javascript內(nèi)容就是調(diào)用這個(gè)函數(shù),需要的數(shù)據(jù)都當(dāng)做參數(shù)傳入這個(gè)函數(shù)了。

優(yōu)點(diǎn) - 兼容性好,簡(jiǎn)單易用,支持瀏覽器與服務(wù)器雙向通信
缺點(diǎn) - 只支持GET請(qǐng)求;存在腳本注入以及跨站請(qǐng)求偽造等安全問(wèn)題

補(bǔ)充一點(diǎn),JSONP不使用XMLHttpRequest對(duì)象加載資源,不屬于真正意義上的AJAX。

十五、== 和 === 有什么不同?

通俗的說(shuō)就是===比==要更為嚴(yán)格,===比較過(guò)程中沒(méi)有任何的類型轉(zhuǎn)換。

十六、什么是三元表達(dá)式 (Ternary expression)?“三元 (Ternary)” 表示什么意思?

如名字表示的三元運(yùn)算符需要三個(gè)操作數(shù)。
語(yǔ)法是
條件 ? 結(jié)果1 : 結(jié)果2;
這里你把條件寫在問(wèn)號(hào)(?)的前面后面跟著用冒號(hào)(:)分隔的結(jié)果1和結(jié)果2。滿足條件時(shí)結(jié)果1否則結(jié)果2。

十七、你怎么看 AMD vs. CommonJS?

瀏覽器端異步和服務(wù)器端同步的模塊化編程規(guī)范

十八、請(qǐng)舉出一個(gè)匿名函數(shù)的典型用例?

定義回調(diào)函數(shù),立即執(zhí)行函數(shù),作為返回值的函數(shù),使用方法var foo = function() {}定義的函數(shù)。

十九、描述以下變量的區(qū)別:null,undefined 或 undeclared?該如何檢測(cè)它們?

未定義的屬性、定義未賦值的為undefined,JavaScript訪問(wèn)不會(huì)報(bào)錯(cuò);null是一種特殊的object;NaN是一種特殊的number;undeclared 是未聲明也未賦值的變量,JavaScript訪問(wèn)會(huì)報(bào)錯(cuò)。

二十、在什么時(shí)候你會(huì)使用 document.write()?

DOM方法,可向文檔寫入 HTML 表達(dá)式或 JavaScript 代碼。

二十一、如何實(shí)現(xiàn)下列代碼:[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]) 
   }
}

二十二、解釋 function foo() {} 與 var foo = function() {} 用法的區(qū)別

函數(shù)聲明的兩種方法:

  1. var foo = function () {}
    這種方式是聲明了個(gè)變量,而這個(gè)變量是個(gè)方法,變量在js中是可以改變的。
    也:將一個(gè)匿名函數(shù)賦值給了變量。

  2. function foo() {}
    這種方式是聲明了個(gè)方法,foo這個(gè)名字無(wú)法改變

二十三、請(qǐng)解釋可變 (mutable) 和不變 (immutable) 對(duì)象的區(qū)別。

在 JavaScript 中,對(duì)象是引用類型的數(shù)據(jù),其優(yōu)點(diǎn)在于頻繁的修改對(duì)象時(shí)都是在原對(duì)象的基礎(chǔ)上修改,并不需要重新創(chuàng)建,這樣可以有效的利用內(nèi)存,不會(huì)造成內(nèi)存空間的浪費(fèi),對(duì)象的這種特性可以稱之為 Mutable,中文的字面意思是「可變」。

Immutable 從字面上翻譯成中文是「不可變」。每次修改一個(gè) Immutable 對(duì)象時(shí)都會(huì)創(chuàng)建一個(gè)新的不可變的對(duì)象,在新對(duì)象上操作并不會(huì)影響到原對(duì)象的數(shù)據(jù)。

二十四、使用 Promises 而非回調(diào) (callbacks) 優(yōu)缺點(diǎn)是什么?

Promise是異步編程的一種解決方案,比傳統(tǒng)的解決方案——回調(diào)函數(shù)和事件——更合理和更強(qiáng)大。它由社區(qū)最早提出和實(shí)現(xiàn),ES6將其寫進(jìn)了語(yǔ)言標(biāo)準(zhǔn),統(tǒng)一了用法,原生提供了Promise對(duì)象。

所謂Promise,簡(jiǎn)單說(shuō)就是一個(gè)容器,里面保存著某個(gè)未來(lái)才會(huì)結(jié)束的事件(通常是一個(gè)異步操作)的結(jié)果。從語(yǔ)法上說(shuō),Promise是一個(gè)對(duì)象,從它可以獲取異步操作的消息。Promise提供統(tǒng)一的API,各種異步操作都可以用同樣的方法進(jìn)行處理。

有了Promise對(duì)象,就可以將異步操作以同步操作的流程表達(dá)出來(lái),避免了層層嵌套的回調(diào)函數(shù)。此外,Promise對(duì)象提供統(tǒng)一的接口,使得控制異步操作更加容易。

Promise也有一些缺點(diǎn)。

首先,無(wú)法取消Promise,一旦新建它就會(huì)立即執(zhí)行,無(wú)法中途取消。
其次,如果不設(shè)置回調(diào)函數(shù),Promise內(nèi)部拋出的錯(cuò)誤,不會(huì)反應(yīng)到外部。
第三,當(dāng)處于Pending狀態(tài)時(shí),無(wú)法得知目前進(jìn)展到哪一個(gè)階段(剛剛開始還是即將完成)。

二十五、請(qǐng)解釋同步 (synchronous) 和異步 (asynchronous) 函數(shù)的區(qū)別。

同步調(diào)用,在發(fā)起一個(gè)函數(shù)或方法調(diào)用時(shí),沒(méi)有得到結(jié)果之前,該調(diào)用就不返回,直到返回結(jié)果;

異步調(diào)用的概念和同步相對(duì),在一個(gè)異步調(diào)用發(fā)起后,被調(diào)用者立即返回給調(diào)用者,但調(diào)用者不能立刻得到結(jié)果,被調(diào)用者在實(shí)際處理這個(gè)調(diào)用的請(qǐng)求完成后,通過(guò)狀態(tài)、通知或回調(diào)等方式來(lái)通知調(diào)用者請(qǐng)求處理的結(jié)果。

簡(jiǎn)單地說(shuō),同步就是發(fā)出一個(gè)請(qǐng)求后什么事都不做,一直等待請(qǐng)求返回后才會(huì)繼續(xù)做事;異步就是發(fā)出請(qǐng)求后繼續(xù)去做其他事,這個(gè)請(qǐng)求處理完成后會(huì)通知你,這時(shí)候就可以處理這個(gè)回應(yīng)了。

二十六、你使用哪些工具和技術(shù)來(lái)調(diào)試 JavaScript 代碼?

1.javascript的debugger語(yǔ)句
需要調(diào)試js的時(shí)候,我們可以給需要調(diào)試的地方通過(guò)debugger打斷點(diǎn),代碼執(zhí)行到斷點(diǎn)就會(huì)暫定,這時(shí)候通過(guò)單步調(diào)試等方式就可以調(diào)試js代碼

if (waldo) {
    debugger;
}

這時(shí)候打開console面板,就可以調(diào)試了

2.DOM斷點(diǎn)
DOM斷點(diǎn)是一個(gè)Firebug和chrome DevTools提供的功能,當(dāng)js需要操作打了斷點(diǎn)的DOM時(shí),會(huì)自動(dòng)暫停,類似debugger調(diào)試。
使用DOM斷點(diǎn)步驟:
選擇你要打斷點(diǎn)的DOM節(jié)點(diǎn)
右鍵選擇Break on..
選擇斷點(diǎn)類型

另外的調(diào)試方法例如alert, console.log,查看元素等就不再贅述了。

二十七、你會(huì)使用怎樣的語(yǔ)言結(jié)構(gòu)來(lái)遍歷對(duì)象屬性 (object properties) 和數(shù)組內(nèi)容?

for in 語(yǔ)句
一般for循環(huán)
數(shù)組forEach方法

感謝各位的閱讀,以上就是“分享JavaScript常見(jiàn)面試題”的內(nèi)容了,經(jīng)過(guò)本文的學(xué)習(xí)后,相信大家對(duì)分享JavaScript常見(jiàn)面試題這一問(wèn)題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是億速云,小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI