1. 程式人生 > >30-撩課大前端-面試寶典-第三十篇

30-撩課大前端-面試寶典-第三十篇

1.什麼叫優雅降級和漸進增強?


優雅降級:
Web站點在所有新式瀏覽器中都能正常工作,
如果使用者使用的是老式瀏覽器,
則程式碼會針對舊版本的IE進行降級處理了,
使之在舊式瀏覽器上以某種形式降級體驗卻不至於完全不能用。
如:border-shadow

漸進增強:
從被所有瀏覽器支援的基本功能開始,
逐步地新增那些只有新版本瀏覽器才支援的功能,
向頁面增加不影響基礎瀏覽器的額外樣式和功能的。
當瀏覽器支援時,它們會自動地呈現出來併發揮作用。
如:預設使用flash上傳,
但如果瀏覽器支援 HTML5 的檔案上傳功能,
則使用HTML5實現更好的體驗;

2.舉一些ES6對Object型別做的常用升級優化?


優化部分

物件屬性變數式宣告。
ES6可以直接以變數形式宣告物件屬性或者方法。
比傳統的鍵值對形式宣告更加簡潔,
更加方便,語義更加清晰.

let [apple, orange] = ['red appe', 'yellow orange'];

// let myFruits = {apple: 'red appe', orange: 'yellow orange'};
let myFruits = {apple, orange};   
尤其在物件解構賦值(見優化部分b.)或者模組輸出變數時,
這種寫法的好處體現的最為明顯

let {keys, values, entries} = Object;

// let MyOwnMethods = {keys: keys, values: values, entries: entries}
let MyOwnMethods = {keys, values, entries};

可以看到屬性變數式宣告屬性看起來更加簡潔明瞭。
方法也可以採用簡潔寫法

let es5Fun = {
    method: function(){}
}; 

let es6Fun = {
    method(){}
}
物件的解構賦值。 
ES6物件也可以像陣列解構賦值那樣,
進行變數的解構賦值

let {apple, orange} = {apple: 'red appe', orange: 'yellow orange'};

物件的擴充套件運算子(...)。 
ES6物件的擴充套件運算子和陣列擴充套件運算子用法本質上差別不大,
畢竟陣列也就是特殊的物件。
物件的擴充套件運算子一個最常用也最好用的用處就在於可以輕鬆的取出
一個目標物件內部全部或者部分的可遍歷屬性,
從而進行物件的合併和分解

let {apple, orange, ...otherFruits} =
{apple: 'red apple', orange: 'yellow orange', grape: 'purple grape', peach: 'sweet peach'}; 
// otherFruits  {grape: 'purple grape', peach: 'sweet peach'}
// 注意: 物件的擴充套件運算子用在解構賦值時,
// 擴充套件運算子只能用在最有一個引數(otherFruits後面不能再跟其他引數)
let moreFruits = {watermelon: 'nice watermelon'};
let allFruits = {apple, orange, ...otherFruits, ...moreFruits};

super 關鍵字。
ES6在Class類裡新增了類似this的關鍵字super。
同this總是指向當前函式所在的物件不同,
super關鍵字總是指向當前函式所在物件的原型物件

升級部分

ES6在Object原型上新增了is()方法,
做兩個目標物件的相等比較,

//false其實是不合理的,Object.is修復了這個小bug。
//(Object.is(NaN, NaN) // true)
用來完善'==='方法。
'==='方法中NaN === NaN 

ES6在Object原型上新增了assign()方法,
用於物件新增屬性或者多個物件合併

const target = { a: 1 };
const source1 = { b: 2 };
const source2 = { c: 3 };
Object.assign(target, source1, source2);
target // {a:1, b:2, c:3}

注意: 
assign合併的物件target只能合併source1、source2中的自身屬性,
並不會合併source1、source2中的繼承屬性,
也不會合並不可列舉的屬性,
且無法正確複製get和set屬性(會直接執行get/set函式,取return的值)

ES6在Object原型上新增了getOwnPropertyDescriptors()方法,
此方法增強了ES5中getOwnPropertyDescriptor()方法,
可以獲取指定物件所有自身屬性的描述物件。
結合defineProperties()方法,
可以完美複製物件,
包括複製get和set屬性
ES6在Object原型上新增了getPrototypeOf()和setPrototypeOf()方法,
用來獲取或設定當前物件的prototype物件。
這個方法存在的意義在於,
ES5中獲取設定prototype對像是通過__proto__屬性來實現的,
然而__proto__屬性並不是ES規範中的明文規定的屬性,
只是瀏覽器各大產商“私自”加上去的屬性,
只不過因為適用範圍廣而被預設使用了,
再非瀏覽器環境中並不一定就可以使用,
所以為了穩妥起見,
獲取或設定當前物件的prototype物件時,
都應該採用ES6新增的標準用法
ES6在Object原型上還新增了Object.keys(),
Object.values(),Object.entries()方法,
用來獲取物件的所有鍵、所有值和所有鍵值對陣列

3.舉一些ES6對Function函式型別做的常用升級優化?


優化部分:

箭頭函式(核心)。
箭頭函式是ES6核心的升級項之一,
箭頭函式裡沒有自己的this,
這改變了以往JS函式中最讓人難以理解的this執行機制。

主要優化點:

箭頭函式內的this指向的是函式定義時所在的物件,
而不是函式執行時所在的物件。
ES5函式裡的this總是指向函式執行時所在的物件,
這使得在很多情況下this的指向變得很難理解,
尤其是非嚴格模式情況下,
this有時候會指向全域性物件,
這甚至也可以歸結為語言層面的bug之一。

ES6的箭頭函式優化了這一點,
它的內部沒有自己的this,這也就導致了this總是指向上一層的this,
如果上一層還是箭頭函式,則繼續向上指,
直到指向到有自己this的函式為止,並作為自己的this
箭頭函式不能用作建構函式,
因為它沒有自己的this,無法例項化
也是因為箭頭函式沒有自己的this,
所以箭頭函式 內也不存在arguments物件。(可以用擴充套件運算子代替)
函式預設賦值。

ES6之前,
函式的形參是無法給預設值得,
只能在函式內部通過變通方法實現。
ES6以更簡潔更明確的方式進行函式預設賦值

function es6Fuc (x, y = 'default') {
    console.log(x, y);
}
es6Fuc(4) // 4, default

升級部分

ES6新增了雙冒號運算子,
用來取代以往的bind,call,和apply。(瀏覽器暫不支援,Babel已經支援轉碼)

foo::bar;
// 等同於
bar.bind(foo);

foo::bar(...arguments);
// 等同於
bar.apply(foo, arguments);

4.Generator函式是什麼,有什麼作用?


如果說JavaScript是ECMAScript標準的一種具體實現、
Iterator遍歷器是Iterator的具體實現,
那麼Generator函式可以說是Iterator介面的具體實現方式。
執行Generator函式會返回一個遍歷器物件,
每一次Generator函式裡面的yield都相當一次遍歷器物件的next()方法,
並且可以通過next(value)方法傳入自定義的value,來改變Generator函式的行為。
Generator函式可以通過配合Thunk 函式更輕鬆更優雅的實現非同步程式設計和控制流管理。

5.什麼是 Babel?


Babel 是一個 JS 編譯器,
自帶一組 ES6 語法轉化器,
用於轉化 JS 程式碼。 
這些轉化器讓開發者提前使用最新的 JS語法(ES6/ES7),
而不用等瀏覽器全部相容。
Babel 預設只轉換新的 JS 句法(syntax),
而不轉換新的API。