記錄昨天面試的6道面試題(內含答案) Proxy 對象的鍵支持什麼類型 Symbol JSONP CORS webpack的proxy是如何解決跨域的?

今天被抓差給候選者進行初面。在這裏記錄一下面試中涉及的幾個知識點。

每次面試我都會遞給候選者一瓶水,這樣可以讓候選者沒那麼緊張,有更好的狀態進行面試,畢竟面試是雙向選擇,公司也需要儘快找到合適的人,沒那麼多網上說的心理戰。

這裏我還想吐槽一下面試造火箭工作擰螺絲,尤其是開發行業,很多面試官針對自己擅長的方向大問特問,完全忽略了候選人的優勢,從而給候選人帶來一個極差的面試體驗。面試最好還是要通過候選人身上的優點來判斷對方是否適合加入你的團隊。

正常的面試應該是按照候選人簡歷中涉及的技術點發問,不然面試時給你一份簡歷幹嘛,至於簡歷中未涉及的知識點有沒有必要問,我覺得沒什麼必要的,因爲很多人在寫簡歷的時候都是力求全面,恨不得聽說過的知識點都寫上熟悉。所以按照簡歷提問就可以了。除此之外再問一些最近流行的技術,主要考察的是候選人對新技術的敏感性和對新事物的接受能力。

如果其中涉及到候選人回答不上的問題也需要給候選人做一番解答,畢竟人家那麼遠來你這面試,總要有所收穫不是。

最後在簡歷中挑選一個候選人比較擅長的點深入來問,這個環節我一般稱爲定級,前面的問題如果回答的不錯,這個人基本就通過了,到最後就要給人定級。如果前面問題回答的不理想基本也到不了這個環節。

Proxy

在2020年來看Proxy早已經不是一個陌生的詞了,他能做的是有很多,尤其在Vue3.0通過Proxy來重構之後,很多面試官喜歡問這個Proxy以及和Object.defineProperty的對比。

Proxy是專門爲對象設置訪問代理器的,通過Proxy可以輕鬆監視到對象的讀寫過程,相比於defineProperty,Proxy他的功能要更爲強大甚至使用起來也更爲方便。

這裏我們定義一個person對象,我們通過new Proxy的方式來去爲我們的person來創建一個代理對象。

Proxy構造函數的第一個參數就是我們需要代理的對象,這裏是person,第二個參數也是一個對象,我們可以把這個對象稱之爲代理的處理對象,這個對象中可以通過get方法來去監視屬性的訪問,通過set方法來去介紹對象當中設置屬性這樣的一個過程。

const person = {
    name: 'yd',
    age: 18
}

const personProxy = new Proxy(person, {
    get() {},
    set() {}
})

先來看get方法,這個方法最簡單可以接收兩個參數,第一個就是所代理的目標對象,第二個就是外部所訪問的這個屬性的屬性名。這個方法的返回值將會作爲外部去訪問這個屬性得到的結果。

{
    get(target, property) {
        console.log(target, property);
        return property in target ? target[property] : undefined;
    }
}

再來看下set方法,這個方法默認接收三個參數, 分別是代理目標對象,以及我們要寫入的屬性名稱還有最後我們要寫入的屬性值。 我們可以做一些校驗,比如說如果設置的是age,他的值就必須是整數,否則就拋錯。

{
    set(target, property, value) {
        console.log(target, property, value);
        if (property === 'age') {
            if (!Number.isInteger(value)) {
                throw new TypeError(``${value} must be a integer);
            }
        }
        target[property] = value;
    }
}

相比於Object.defineProperty, Proxy到底有哪些優勢。

首先最明顯的優勢就是在於Proxy要更爲強大一些,那這個強大具體體現在Object.defineProperty只能監聽到對象屬性的讀取或者是寫入,而Proxy除讀寫外還可以監聽對象中屬性的刪除,對對象當中方法的調用等等。

第二點優勢就是對於數組對象進行監視,通常我們想要監視數組的變化,基本要依靠重寫數組方法,這也是Vue的實現方式,proxy可以直接監視數組的變化。以往我們想要通過Object.defineProperty去監視數組的操作最常見的方式是重寫數組的操作方法,這也是Vue.js中所使用的方式,大體的方式就是通過自定義的方法去覆蓋掉數組原型對象上的push,shift之類的方法,以此來劫持對應的方法調用的過程。

對象的鍵支持什麼類型

這個問題考察的是候選人的基礎知識是否紮實。

很多人都會認爲對象的鍵是字符串類型,如果在以前確實沒錯,但是ES2015版本中對象的鍵類型還可以是Symbol。

const person = {
    name: 'yd',
    [Symbol()]: 18
}

這也是引出下面的Symbol。

Symbol

在ECMAScript2015之前,對象的屬性名都是字符串,而字符串是有可能會重複的。如果重複的話就會產生衝突。

以前解決這種問題最好的方式就是約定,但是約定的方式只是規避了問題並不是徹底解決了這個問題。如果在這個過程中有人不遵守約定那這個問題仍然會存在。

ES2015爲了解決這個問題提供了一種全新的原始數據類型Symbol,翻譯過來的意思叫做符號,翻譯過來就是表示一個獨一無二的值。 通過Symbol函數就可以創建一個Symbol類型的數據,而且這種類型的數據typeof的結果就是symbol,那這也就表示他確實是一個全新的類型。

const s = Symbol();
typeof s; // symbol類型

這種類型最大的特點就是獨一無二,也就是說我們通過Symbol函數創建的每一個值都是唯一的。他永遠不會重複。

Symbol() === Symbol(); // false

考慮到在開發過程中的調試Symbol創建時允許接收一個字符串,作爲這個值的描述文本, 對於我們多次使用Symbol時就可以區分出是哪一個Symbol,但這個參數也僅是描述作用,相同的描述字段生成的值仍是不同的。

const s1 = Symbol('foo');
const s2 = Symbol('foo');

s1 === s2; // false

從ES2015開始,對象就已經允許使用Symbol作爲屬性名。那也就是說現在對象的屬性名可以是兩種類型,字符串和Symbol。

const person = {
    [Symbol()]: 123,
    [Symbol()]: 456
}

如果我們需要在全局去複用一個相同的Symbol值,我們可以使用全局變量的方式去實現,或者是使用Symbol類型提供的一個靜態方法去實現。具體就是Symbol的靜態方法for,這個方法接收一個字符串作爲參數,相同的參數一定對應相同的值。

const s1 = Symbol.for('foo');
const s2 = Symbol.for('foo');

s1 === s2; // true

這個方法維護了一個全局的註冊表,爲字符串和Symbol提供了一個對應關係。需要注意的是,在內部維護的是字符串和Symbol的關係,那也就是說如參數不是字符串,會轉換爲字符串。

const s1 = Symbol.for('true');
const s2 = Symbol.for(true);

s1 === s2; // true

JSONP

很多人對jsonp的理解都停留在概念上,沒有真正理解過他的原理,他爲什麼可以跨域,當然不僅僅是script標籤不受同源策略影響,實際上jsonp是一種前後端約定的解決方案。

不過現在基本已經很少用到了。因爲現在已經有了更流行的CORS方案,相對來說也會更安全,不過jsonp還是有其自身的優勢的。

很多人都知道瀏覽器的同源策略,就是發送請求的頁面地址和被請求的接口地址的域名,協議,端口三者必須一致,否則瀏覽器就會攔截這種請求。瀏覽器攔截的意思不是說請求發佈出去,請求還是可以正常觸達服務器的,如果服務器正常返回了瀏覽器也會接收的到,只是不會交給我們所在的頁面。這一點查看network是可以看到的。

jsonp一般是利用script標籤的src屬性,對於服務器來說只有請求和響應兩種操作,請求來了就會響應,無論響應的是什麼。請求的類型實在太多了。

瀏覽器輸入一個url是一個請求,ajax調用一個接口也是一個請求,img和script的src也是請求。這些地址都會觸達服務器。那爲什麼jsonp一般會選用script標籤呢,首先大家都知道script加載的js是沒有跨域限制的,因爲加載的是一個腳本,不是一個ajax請求。 你可以理解爲瀏覽器限制的是XMLHttpRequest這個對象,而script是不使用這個對象的。

僅僅沒有限制還不夠,還有一個更重要的點因爲script是執行js腳本的標籤,他所請求到的內容會直接當做js來執行。

這也可以看出,jsonp和ajax對返回參數的要求是不同的,jsonp需要服務返回一段js腳本,ajax需要返回的是數據。

因此這就要求服務器單獨來處理jsonp這中請求,一般服務器接口會把響應的數據通過函數調用的方式返回,比如說返回的內容是'yd',那就要返回成cb('yd')

cb('yd')

這是一段函數調用的腳本,通過script標籤加載之後會立即執行的,如果我們在全局定義一個cb函數。那麼這段腳本執行的時候就會調用到我們定義的那個函數,函數中的參數就是服務返回的值了。前端也就可以在這個函數中獲取到了。

function cb (data) {
    console.log(data);
}

所以說jsonp是前後端共同約定的一種結果。

CORS

瀏覽器通過同源策略來限制前後端的跨域問題,但同時也給了相應的解決方案。

服務器在返回相應的時候可以通過設置響應頭來允許哪些網址跨域請求,這樣前端就可以成功拿到響應的結果了。所以這也證實了,前端拿不到結果不是服務器不返回,而是瀏覽器沒有給到前端。

Access-Control-Allow-Origin: www.xxxx.com

webpack的proxy是如何解決跨域的?

前面說了,跨域是因爲瀏覽器的同源策略限制,問題發生在瀏覽器身上,那我們是不是可以避過瀏覽器呢。前面我寫過一篇前端需要知道的nginx,裏面介紹了反向代理和負載均衡,其實這裏就像是反向代理一樣。

我們在使用webpack開發項目的時候,webpack的dev-server模塊會啓動一個服務器,這個服務器不止幫我們做了自動更新,同時也可以做到反向代理。

就是我們把請求發送給webpack-dev-server, 然後webpack-dev-server再去請求後端服務器,服務之間的請求是沒有跨域問題的,只要後端返回了webpack-dev-server就能拿到,然後再返回給前端。

好了基本上就問了這幾個問題,老闆說面試時間控制在20分鐘左右。

小編這裏也整理了小米、騰訊、網易等一線大廠2020年最新面試資料。

需要的可以點擊此處即可免費獲取,記得備註簡書哦,否則不予通過

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章