前言:正所謂金三銀四,我也在三月份面了一次荔枝FM,初試是作一套比較簡單的筆試題,發出來跟你們簡單探討一下,面試時的一些問題主要是經過這些筆試題進行拓展,例如flex佈局、改變正則條件,promise事件機制等等,會在下一篇文章中提到,這篇文章僅爲初面的筆試題javascript
function outter () {
return inner;
function inner () {}
var inner;
inner = 9;
}
//問題是下面代碼執行輸出值是什麼:
typeof outter();
複製代碼
答案:這道題不單只是考變量提高,由於這裏還有函數提高,那就是還要考函數提高和變量提高究竟誰優先級更高了。css
根據 《你不知道的JavaScript(上卷)》 裏的說法,js引擎在解釋代碼以前會先進行編譯,編譯階段會將全部的變量聲明和函數聲明與相關做用域關聯起來,而且將這些聲明提高到做用域頂部,而後到代碼執行階段纔會進行變量賦值。html
雖然第一行代碼就是return inner
, 可是根據上面的結論,var inner
的變量聲明和function inner() {}
的函數聲明會第一時間被提高到頂部。java
那麼剩下的問題就是究竟函數優先仍是變量優先,答案天然也在書中找獲得,那就是函數優先,函數優先提高後,因爲inner
已經被聲明爲函數變量,後面var inner
時編譯器進行LHS,也就是左查詢,發現同一做用域中已經有該值會忽略該變量聲明,所以這題的答案是字符串'function'
;面試
<html>
<div class="box"></div>
</html>
<style> .box { width: 45vw; height: 45vw; } </style>
複製代碼
我這是使用最新標準也最簡單的實現方式了,你們能夠在評論寫一寫本身的實現方式。正則表達式
html:數組
<div class="one">
<div class="two"></div>
<div class="three"></div>
</div>
<div class="four">
<div class="five"></div>
<div class="six"></div>
</div>
複製代碼
css:promise
.one {
position: relative;
z-index: 2;
.two {
z-index: 6;
}
.three {
position: absolute;
z-index: 5;
}
}
.four {
position: absolute;
z-index: 1;
.five {}
.six {
position: absolute;
top: 0;
left: 0;
z-index: -1;
}
}
複製代碼
PS:其實這道題代碼寫的不大好,由於沒有div寬度和高度,甚至.one和.four也不重疊,就算本身把代碼跑起來也是沒法看出是否重疊的,所以須要本身去加點東西,不過主要知道考點是什麼就行了。app
解析以下:從w3c的文檔能夠知道,z-index屬性設置一個定位元素沿 z 軸的位置,z 軸定義爲垂直延伸到顯示區的軸。若是爲正數,則離用戶更近,爲負數則表示離用戶更遠。異步
經過上面幾點能夠得出答案是 .three .two .one .five .six .four,可是這只是元素層疊順序的冰山一角,更深刻的瞭解能夠讀一下張旭鑫大神的文章。
還有疑問的能夠直接經過代碼看效果:元素z-index的堆疊順序
拓展閱讀:深刻理解CSS中的層疊上下文和層疊順序
(1)字符串長度爲8-12
(2)字符串只包含英文和數字
這道題算是送分題,只要對正則有所瞭解就能答出,並且答案不止一個,你們能夠寫寫看本身的答案
/(\d|[A-z]{8,12})/
複製代碼
function a () {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('/a');
}, 1000);
});
}
function b () {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('/b');
}, 2000);
});
}
function c () {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('/c');
}, 500);
});
}
function d () {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('/d');
}, 3000);
});
}
// Promise.race競賽方法在第一個請求resolve後就立馬進入then,能夠算出最快接口的時間
const startTime = new Date / 1;
Promise.race([a(), b(), c(), d()]).then(o => {
const endTime = new Date / 1;
console.log(`接口${o}最快完成請求,請求時長爲${endTime - startTime}`);
});
複製代碼
要求:構造函數不能直接執行,必須使用new,每一個實例不互相影響參數列表以下
參數名 | 類型 | 默認值 |
---|---|---|
title | String | XXXX(不記得了) |
body | String | '' |
cancelText | String | 取消 |
okText | String | 確認 |
具備show和close方法,能夠經過on綁定相關事件,off解綁相關事件。
須要達成效果以下:
let dialog = new Dialog();
dialog.on('show', () => {
console.log('Dialog Show');
});
dialog.on('close', () => {
console.log('Dialog Close');
});
dialog.show(); // 輸出Dialog Show;
setTimeout(() => {
dialog.close(); // 輸出Dialog Close;
}, 3000);
複製代碼
答案:這道題看起來也是少了不少細節, 不過這是一種經常使用的彈窗組件,所以咱們能夠本身給它補上應有的功能。
class Dialog {
// show方法的回調函數數組
showCallbacks = [];
// close方法的回調函數數組
closeCallbacks = [];
// 構造函數初始化參數
constructor(options) {
this.options = Object.assign(
{
title: "title",
body: "是否確認是一個dialog",
cancelText: "取消",
okText: "確認"
},
options
);
document.body.appendChild(this.renderTemplate());
this.initEvent();
}
// 渲染彈窗模板方法
renderTemplate() {
const { title, body, cancelText, okText } = this.options;
this.container = document.createElement("div");
this.container.classList = "dialog-container";
this.container.innerHTML = `<div class="dialog-title">${title}</div> <div class="dialog-body">${body}</div> <div class="dialog-footer"> <div class="dialog-confirm">${okText}</div> <div class="dialog-cancel">${cancelText}</div> </div>`;
return this.container;
}
// 初始化事件
initEvent() {
this.container
.querySelector(".dialog-confirm")
.addEventListener("click", () => {
this.close();
});
this.container
.querySelector(".dialog-cancel")
.addEventListener("click", () => {
this.close();
});
}
// 事件綁定
on(type, callback) {
if (!callback || typeof callback !== "function")
throw new Error("callback必須是函數");
this[`${type}Callbacks`].push(callback);
}
// 事件解綁
off(type, callback) {
if (callback && typeof callback === "function") {
// 將函數toString後在回調數組中查找對比。
callback = callback.toString();
this[`${type}Callbacks`].forEach((v, i) => {
// 一樣的回調函數將一次性所有解綁
if (v.toString === callback) {
// 刪除事件回調數組中的值
this[`${type}Callbacks`].splice(i, ++i);
}
});
return;
}
// 若是不傳callback,清空整個回調函數數組
this[`${type}Callbacks`] = [];
}
// show方法,執行show回調函數數組
show() {
this.container.style.display = "block";
this.showCallbacks.forEach(callback => {
callback();
});
}
// close方法,執行close回調函數數組
close() {
this.container.style.display = "none";
this.closeCallbacks.forEach(callback => {
callback();
});
}
}
複製代碼
示例代碼:實現一個Dialog彈窗
最後這道題其實有兩道題,選擇其中之一做答,不過期間有限,我沒作另外一道題因此沒記住問題是什麼,順便吐槽一下那個答題頁面打代碼時真的很不順手,嚴重影響答題效率。
上面的答案可能並不必定對或者並非最佳答案,畢竟我的答案或有缺漏,但願有更好答案的朋友能夠在評論寫一下,謝謝你們的閱讀。