首頁  >  文章  >  web前端  >  JavaScrip的常見面試問題及答案總結

JavaScrip的常見面試問題及答案總結

不言
不言轉載
2018-12-11 09:58:482231瀏覽

這篇文章帶給大家的內容是關於JavaScrip的常見面試題目總結,有一定的參考價值,有需要的朋友可以參考一下,希望對你有幫助。

一、請解釋 JavaScript 中 this 是如何運作的。

首先:this 永遠指向函數執行階段所在的對象,而不是函數被建立時所在的物件。匿名函數或不處於任何物件中的函數指向 window 。

1、方法呼叫模式

當函數被儲存為物件的屬性時,成該函數為該物件的方法。函數中this的值為該物件。

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

2、 函數呼叫模式

當函數並不是物件的屬性。函數中this的值為全域物件
note:某個方法中的內部函數中的this的值也是全域對象,而非外部函數的this

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

3、建構器呼叫模式

即使用new呼叫的函數,則其中this將會被綁定到那個新建構的物件。

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

4、使用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指向所提供的第一個參數。

二、請解釋原型繼承 (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;
}

三、解釋為什麼接下來這段程式碼不是IIFE (立即呼叫的函數表達式):function foo(){ }( ); 要做哪些改動使它變成IIFE?

(function fn(){..})(),函數被包含在一個括號內,變成一個表達式,接著跟著一個(),就立即執行這個函數。

IIFE的一些作用:

  1. 建立作用域,內部保存一些大量臨時變數的程式碼防止命名衝突。

  2. 一些函式庫的外層用這種形式包起來防止作用域污染。

  3. 運行一些只執行一次的程式碼。

四、(function fn(){..})(),函數被包含在一個括號內,變成為一個表達式,隨後跟著一個(),就立即執行這個函數。

IIFE的一些作用:

  1. 建立作用域,內部保存一些大量臨時變數的程式碼防止命名衝突。

  2. 一些函式庫的外層用這種形式包起來防止作用域污染。

  3. 運行一些只執行一次的程式碼。

當某個函數呼叫時會建立一個執行環境以及作用域鏈,然後根據arguments和其它命名參數初始化形成活動物件。在外部函數呼叫結束後,其執行環境與作用域鏈被銷毀,但是其活動物件保存在了閉包之中,最後在閉包函數呼叫結束後才銷毀。簡單的說,閉包就是能夠讀取其他函數內部變數的函數。在js中,閉包是指有權存取另一個函數作用域中的變數的函數。

如何使用:將A函數內部的B函數作為A​​函數的回傳值傳回。

為什麼要:

1、匿名自執行函數

有的場景下函數只需要執行一次,例如init()之類的函數,其內部變數無需維護,我們可以使用閉包。我們創建了一個匿名的函數,並立即執行它,由於外部無法引用它內部的變量,因此在函數執行完後會立刻釋放資源,而且不污染全域物件。

2、封裝

模擬物件導向的程式碼風格進行封裝,使私有屬性存在成為可能。

五、.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

六、請解釋 Function.prototype.bind?

Function.prototype.bind方法会创建一个新函数,当这个新函数被调用时,它的this值是传递给bind()的第一个参数, 它的参数是bind()的其他参数和其原本的参数.

七、请指出 JavaScript 宿主对象 (host objects) 和原生对象 (native objects) 的区别?

宿主对象是指DOM和BOM。
原生对象是Object、Function、Array、String、Boolean、Number、Date、RegExp、Error、Math等对象。

八、请指出以下代码的区别: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的实例对象。

九、请尽可能详尽的解释 Ajax 的工作原理。以及使用 Ajax 都有哪些优劣?

Ajax是无需刷新页面就能从服务器取得数据的一种方法。

Ajax通过XmlHttpRequest对象来向服务器发异步请求,从服务器获得数据,然后用javascript来操作DOM更新页面。

过程

  1. 创建XMLHttpRequest对象。

  2. 设置响应HTTP请求的回调函数。

  3. 创建一个HTTP请求,指定相应的请求方法、url等。

  4. 发送HTTP请求。

  5. 获取服务器端返回的数据。

  6. 使用JavaScript操作DOM更新页面。

缺点

  1. 对搜索引擎不友好

  2. 要实现Ajax下的前后退功能成本较大

  3. 跨域问题限制

十、请解释变量声明提升 (hoisting)。

变量的声明前置就是把变量的声明提升到当前作用域的最前面。
函数的声明前置就是把整个函数提升到当前作用域的最前面(位于前置的变量声明后面)。

//变量的声明前置
console.log(num);//undefined
var num = 1;

等价于

//变量的声明前置
var num;
console.log(num);//undefined
num = 1;

十一、请描述事件冒泡机制 (event bubbling)。

事件冒泡(event bubbling),事件最开始时由触发的那个元素身上发生,然后沿着DOM树向上传播,直到document对象。如果想阻止事件起泡,可以使用e.stopPropagation()。

十二、什么是 “use strict”; ? 使用它的好处和坏处分别是什么?

优点

消除Javascript语法的一些不严谨之处,减少一些怪异行为;
消除代码运行的一些不安全之处,保证代码运行的安全;
提高编译器效率,增加运行速度;
为未来新版本的Javascript做好铺垫。

缺点

严格模式改变了语义。依赖这些改变可能会导致没有实现严格模式的浏览器中出现问题或者错误。

十三、请解释 JavaScript 的同源策略 (same-origin policy)。

同源策略限制了一个源(origin)中加载文本或脚本与来自其它源(origin)中资源的交互方式。同源指的是协议、域名、端口相同,同源策略是一种安全协议。

十四、请解释 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。

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

通俗的说就是===比==要更为严格,===比较过程中没有任何的类型转换。

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

如名字表示的三元运算符需要三个操作数。
语法是
条件 ? 结果1 : 结果2;
这里你把条件写在问号(?)的前面后面跟着用冒号(:)分隔的结果1和结果2。满足条件时结果1否则结果2。

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

浏览器端异步和服务器端同步的模块化编程规范

十八、请举出一个匿名函数的典型用例?

定义回调函数,立即执行函数,作为返回值的函数,使用方法var foo = function() {}定义的函数。

十九、描述以下变量的区别:null,undefined 或 undeclared?该如何检测它们?

未定义的属性、定义未赋值的为undefined,JavaScript访问不会报错;null是一种特殊的object;NaN是一种特殊的number;undeclared 是未声明也未赋值的变量,JavaScript访问会报错。

二十、在什么时候你会使用 document.write()?

DOM方法,可向文档写入 HTML 表达式或 JavaScript 代码。

二十一、如何实现下列代码:[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() {} 用法的区别

函数声明的两种方法:

  1. var foo = function () {}

这种方式是声明了个变量,而这个变量是个方法,变量在js中是可以改变的。
也:将一个匿名函数赋值给了变量。

  1. function foo() {}

这种方式是声明了个方法,foo这个名字无法改变

二十三、请解释可变 (mutable) 和不变 (immutable) 对象的区别。

在 JavaScript 中,对象是引用类型的数据,其优点在于频繁的修改对象时都是在原对象的基础上修改,并不需要重新创建,这样可以有效的利用内存,不会造成内存空间的浪费,对象的这种特性可以称之为 Mutable,中文的字面意思是「可变」。

Immutable 从字面上翻译成中文是「不可变」。每次修改一个 Immutable 对象时都会创建一个新的不可变的对象,在新对象上操作并不会影响到原对象的数据。

二十四、使用 Promises 而非回调 (callbacks) 优缺点是什么?

Promise是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。它由社区最早提出和实现,ES6将其写进了语言标准,统一了用法,原生提供了Promise对象。

所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise是一个对象,从它可以获取异步操作的消息。Promise提供统一的API,各种异步操作都可以用同样的方法进行处理。

有了Promise对象,就可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。此外,Promise对象提供统一的接口,使得控制异步操作更加容易。

Promise也有一些缺点。

首先,无法取消Promise,一旦新建它就会立即执行,无法中途取消。
其次,如果不设置回调函数,Promise内部抛出的错误,不会反应到外部。
第三,当处于Pending状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。

二十五、请解释同步 (synchronous) 和异步 (asynchronous) 函数的区别。

同步调用,在发起一个函数或方法调用时,没有得到结果之前,该调用就不返回,直到返回结果;

异步调用的概念和同步相对,在一个异步调用发起后,被调用者立即返回给调用者,但调用者不能立刻得到结果,被调用者在实际处理这个调用的请求完成后,通过状态、通知或回调等方式来通知调用者请求处理的结果。

简单地说,同步就是发出一个请求后什么事都不做,一直等待请求返回后才会继续做事;异步就是发出请求后继续去做其他事,这个请求处理完成后会通知你,这时候就可以处理这个回应了。

二十六、你使用哪些工具和技术来调试 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,查看元素等就不再赘述了。

二十七、你会使用怎样的语言结构来遍历对象属性 (object properties) 和数组内容?

for in 语句
一般for循环
数组forEach方法

以上是JavaScrip的常見面試問題及答案總結的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:segmentfault.com。如有侵權,請聯絡admin@php.cn刪除