荔枝FM的前端筆試題

前言:正所謂金三銀四,我也在三月份面了一次荔枝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和css實現一個寬度爲屏幕45%的正方形,可以使用最新標準

<html>
    <div class="box"></div>
</html>
<style> .box { width: 45vw; height: 45vw; } </style>
複製代碼

我這是使用最新標準也最簡單的實現方式了,你們能夠在評論寫一寫本身的實現方式。正則表達式

 

三、寫出6個div元素的堆疊順序,最上面的在第一個位置,例如: .one .two .three .four .five .six(z-index)

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 軸定義爲垂直延伸到顯示區的軸。若是爲正數,則離用戶更近,爲負數則表示離用戶更遠。異步

  1. 沒有定位的元素z-index是不生效的
  2. 定位元素擁有更高堆疊順序的元素老是會處於堆疊順序較低的定位元素的前面
  3. 子元素必然在父元素的前面,不論是否是定位元素
  4. 同級定位元素的z-index相同時遵循「後來居上」,後面的定位元素堆疊順序更前
  5. z-index小於0的定位元素處於全部元素的後面,僅在層疊上下文的背景顏色和邊框前面

經過上面幾點能夠得出答案是 .three .two .one .five .six .four,可是這只是元素層疊順序的冰山一角,更深刻的瞭解能夠讀一下張旭鑫大神的文章。

還有疑問的能夠直接經過代碼看效果:元素z-index的堆疊順序

拓展閱讀:深刻理解CSS中的層疊上下文和層疊順序

 

四、寫出能匹配如下兩個要求的正則表達式

(1)字符串長度爲8-12

(2)字符串只包含英文和數字

這道題算是送分題,只要對正則有所瞭解就能答出,並且答案不止一個,你們能夠寫寫看本身的答案

/(\d|[A-z]{8,12})/
複製代碼

 

五、四個請求接口分別是/a、/b、/c、/d,算出最快請求回來的那個接口的耗時時長(可用setTimeout模擬異步請求)

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}`);
});
複製代碼

 

六、實現一個模態框dialog

要求:構造函數不能直接執行,必須使用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彈窗

最後這道題其實有兩道題,選擇其中之一做答,不過期間有限,我沒作另外一道題因此沒記住問題是什麼,順便吐槽一下那個答題頁面打代碼時真的很不順手,嚴重影響答題效率。

 

上面的答案可能並不必定對或者並非最佳答案,畢竟我的答案或有缺漏,但願有更好答案的朋友能夠在評論寫一下,謝謝你們的閱讀。

相關文章
相關標籤/搜索