1. 程式人生 > >前端面試-基礎javascript篇

前端面試-基礎javascript篇

1. get請求傳參長度的誤區

誤區:我們經常說get請求引數的大小存在限制,而post請求的引數大小是無限制的。

實際上HTTP 協議從未規定 GET/POST 的請求長度限制是多少。對get請求引數的限制是來源與瀏覽器或web伺服器,瀏覽器或web伺服器限制了url的長度。為了明確這個概念,我們必須再次強調下面幾點:

  • HTTP 協議 未規定 GET 和POST的長度限制
  • GET的最大長度顯示是因為 瀏覽器和 web伺服器限制了 URI的長度
  • 不同的瀏覽器和WEB伺服器,限制的最大長度不一樣
  • 要支援IE,則最大長度為2083byte,若只支援Chrome,則最大長度 8182byte

2. 補充get和post請求在快取方面的區別

post/get的請求區別,具體不再贅述。

補充補充一個get和post在快取方面的區別:

  • get請求類似於查詢的過程,使用者獲取資料,可以不用每次都與資料庫連線,所以可以使用快取。
  • post不同,post做的一般是修改和刪除的工作,所以必須與資料庫互動,所以不能使用快取。因此get請求適合於請求快取。

3. 閉包

一句話可以概括:閉包就是能夠讀取其他函式內部變數的函式,或者子函式在外呼叫,子函式所在的父函式的作用域不會被釋放。

4. 類的建立和繼承

(1)類的建立(es5):new一個function,在這個function的prototype裡面增加屬性和方法。

下面來建立一個Animal類:

// 定義一個動物類
function Animal (name) {
  // 屬性
  this.name = name || 'Animal';
  // 例項方法
  this.sleep = function(){
    console.log(this.name + '正在睡覺!');
  }
}
// 原型方法
Animal.prototype.eat = function(food) {
  console.log(this.name + '正在吃:' + food);
};
複製程式碼

這樣就生成了一個Animal類,實力化生成物件後,有方法和屬性。

(2)類的繼承——原型鏈繼承

--原型鏈繼承
function Cat(){ }
Cat.prototype = new Animal();
Cat.prototype.name = 'cat';
// Test Code
var cat = new Cat();
console.log(cat.name);
console.log(cat.eat('fish'));
console.log(cat.sleep());
console.log(cat instanceof Animal); //true 
console.log(cat instanceof Cat); //true
複製程式碼
  • 介紹:在這裡我們可以看到new了一個空物件,這個空物件指向Animal並且Cat.prototype指向了這個空物件,這種就是基於原型鏈的繼承。
  • 特點:基於原型鏈,既是父類的例項,也是子類的例項
  • 缺點:無法實現多繼承

(3)構造繼承:使用父類的建構函式來增強子類例項,等於是複製父類的例項屬性給子類(沒用到原型)

function Cat(name){
  Animal.call(this);
  this.name = name || 'Tom';
}
// Test Code
var cat = new Cat();
console.log(cat.name);
console.log(cat.sleep());
console.log(cat instanceof Animal); // false
console.log(cat instanceof Cat); // true
複製程式碼
  • 特點:可以實現多繼承
  • 缺點:只能繼承父類例項的屬性和方法,不能繼承原型上的屬性和方法。

(4)例項繼承和拷貝繼承

例項繼承:為父類例項新增新特性,作為子類例項返回

拷貝繼承:拷貝父類元素上的屬性和方法

上述兩個實用性不強,不一一舉例。

(5)組合繼承:相當於構造繼承和原型鏈繼承的組合體。通過呼叫父類構造,繼承父類的屬性並保留傳參的優點,然後通過將父類例項作為子類原型,實現函式複用

function Cat(name){
  Animal.call(this);
  this.name = name || 'Tom';
}
Cat.prototype = new Animal();
Cat.prototype.constructor = Cat;
// Test Code
var cat = new Cat();
console.log(cat.name);
console.log(cat.sleep());
console.log(cat instanceof Animal); // true
console.log(cat instanceof Cat); // true
複製程式碼
  • 特點:可以繼承例項屬性/方法,也可以繼承原型屬性/方法
  • 缺點:呼叫了兩次父類建構函式,生成了兩份例項

(6)寄生組合繼承:通過寄生方式,砍掉父類的例項屬性,這樣,在呼叫兩次父類的構造的時候,就不會初始化兩次例項方法/屬性

function Cat(name){
  Animal.call(this);
  this.name = name || 'Tom';
}
(function(){
  // 建立一個沒有例項方法的類
  var Super = function(){};
  Super.prototype = Animal.prototype;
  //將例項作為子類的原型
  Cat.prototype = new Super();
})();
// Test Code
var cat = new Cat();
console.log(cat.name);
console.log(cat.sleep());
console.log(cat instanceof Animal); // true
console.log(cat instanceof Cat); //true
複製程式碼
  • 較為推薦

5. 如何解決非同步回撥地獄

promise、generator、async/await

6. 說說前端中的事件流

HTML中與javascript互動是通過事件驅動來實現的,例如滑鼠點選事件onclick、頁面的滾動事件onscroll等等,可以向文件或者文件中的元素新增事件偵聽器來預訂事件。想要知道這些事件是在什麼時候進行呼叫的,就需要了解一下“事件流”的概念。

什麼是事件流:事件流描述的是從頁面中接收事件的順序,DOM2級事件流包括下面幾個階段。

  • 事件捕獲階段
  • 處於目標階段
  • 事件冒泡階段

addEventListeneraddEventListener 是DOM2 級事件新增的指定事件處理程式的操作,這個方法接收3個引數:要處理的事件名、作為事件處理程式的函式和一個布林值。最後這個布林值引數如果是true,表示在捕獲階段呼叫事件處理程式;如果是false,表示在冒泡階段呼叫事件處理程式。

IE只支援事件冒泡

7. 如何讓事件先冒泡後捕獲

在DOM標準事件模型中,是先捕獲後冒泡。但是如果要實現先冒泡後捕獲的效果,對於同一個事件,監聽捕獲和冒泡,分別對應相應的處理函式,監聽到捕獲事件,先暫緩執行,直到冒泡事件被捕獲後再執行捕獲之間。

8. 事件委託

  • 簡介:事件委託指的是,不在事件的發生地(直接dom)上設定監聽函式,而是在其父元素上設定監聽函式,通過事件冒泡,父元素可以監聽到子元素上事件的觸發,通過判斷事件發生元素DOM的型別,來做出不同的響應。

  • 舉例:最經典的就是ul和li標籤的事件監聽,比如我們在新增事件時候,採用事件委託機制,不會在li標籤上直接新增,而是在ul父元素上新增。

  • 好處:比較合適動態元素的繫結,新新增的子元素也會有監聽函式,也可以有事件觸發機制。

9. 圖片的懶載入和預載入

  • 預載入:提前載入圖片,當用戶需要檢視時可直接從本地快取中渲染。

  • 懶載入:懶載入的主要目的是作為伺服器前端的優化,減少請求數或延遲請求數。

兩種技術的本質:兩者的行為是相反的,一個是提前載入,一個是遲緩甚至不載入。 懶載入對伺服器前端有一定的緩解壓力作用,預載入則會增加伺服器前端壓力。

10. mouseover和mouseenter的區別

  • mouseover:當滑鼠移入元素或其子元素都會觸發事件,所以有一個重複觸發,冒泡的過程。對應的移除事件是mouseout

  • mouseenter:當滑鼠移除元素本身(不包含元素的子元素)會觸發事件,也就是不會冒泡,對應的移除事件是mouseleave

11. js的new操作符做了哪些事情

new 操作符新建了一個空物件,這個物件原型指向建構函式的prototype,執行建構函式後返回這個物件。

12.改變函式內部this指標的指向函式(bind,apply,call的區別)

  • 通過apply和call改變函式的this指向,他們兩個函式的第一個引數都是一樣的表示要改變指向的那個物件,第二個引數,apply是陣列,而call則是arg1,arg2...這種形式。

  • 通過bind改變this作用域會返回一個新的函式,這個函式不會馬上執行。

13. js的各種位置,比如clientHeight,scrollHeight,offsetHeight ,以及scrollTop, offsetTop,clientTop的區別?

  • clientHeight:表示的是可視區域的高度,不包含border和滾動條

  • offsetHeight:表示可視區域的高度,包含了border和滾動條

  • scrollHeight:表示了所有區域的高度,包含了因為滾動被隱藏的部分。

  • clientTop:表示邊框border的厚度,在未指定的情況下一般為0

  • scrollTop:滾動後被隱藏的高度,獲取物件相對於由offsetParent屬性指定的父座標(css定位的元素或body元素)距離頂端的高度。

14. js拖拽功能的實現

  • 首先是三個事件,分別是mousedown,mousemove,mouseup 當滑鼠點選按下的時候,需要一個tag標識此時已經按下,可以執行mousemove裡面的具體方法。

  • clientX,clientY標識的是滑鼠的座標,分別標識橫座標和縱座標,並且我們用offsetX和offsetY來表示元素的元素的初始座標,移動的舉例應該是:

    滑鼠移動時候的座標-滑鼠按下去時候的座標。

    也就是說定位資訊為:

    滑鼠移動時候的座標-滑鼠按下去時候的座標+元素初始情況下的offetLeft.

  • 還有一點也是原理性的東西,也就是拖拽的同時是絕對定位,我們改變的是絕對定位條件下的left 以及top等等值。

補充:也可以通過html5的拖放(Drag 和 drop)來實現



連結:https://juejin.im/post/5b44a485e51d4519945fb6b7