最近接到了荔枝FM的面試通知,遺憾的是沒有拿到offer,但是這次面試呢,還是收穫很大的,下面就來給大家說說我遇到的面試題
一面
一面是直接發了一套面試題到郵箱,開啟了防作弊的,限時20分鐘做完,下面是我一面是的題目
1. 變數提升和函式提升
function outter () { return inner; function inner () {} var inner; inner = 9; } //問題是下面程式碼執行輸出值是什麼: typeof outter();
這題涉及到的知識點是變數提升,在js中是存在變數提升和函式提升的,但是如果變數名重複的情況下函式提升>變數提升
答案:function
2. 用html和css實現一個寬度為螢幕45%的正方形,可以使用最近標準
這題只要考察的是自適應的問題
第一種方法:利用寬度百分比
<div style="width:50%;padding-bottom:50%;height:0px;> </div>
第二種方法:利用css的新單位vw
<div style="width: 50vw; height: 50vw;> </div>
第三題:寫出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:
.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; } }
這題考察的是css部分的層疊上下文的知識點說這個之前呢,我們得了解下面幾個知識點
解析:從w3c的文件可以知道,z-index屬性設定一個定位元素沿 z 軸的位置,z 軸定義為垂直延伸到顯示區的軸。如果為正數,則離使用者更近,為負數則表示離使用者更遠
- 沒有定位的元素z-index是不會生效的
- 定位元素擁有更高堆疊順序的元素總是處於堆疊順序較低的定位元素的前面
- 子元素必然在父元素的前面,不管是否是定位元素
- 同級定位元素的z-index相同時遵循"後來居上",後面的定位元素堆疊順序更前
- z-index小於0的定位元素位於所有元素的後面,但是比其父元素的堆疊順序要前
通過上面的結論分析,得出的答案如下
答案:.three>.two>.one>.five>.six>.four
二面的時候,面試官會根據這題擴充套件問題一下這個問題:
z-index的觸發條件是:
- 根層疊上下文(
html
) - position
- css3屬性
- flex
- transform
- opacity
- filter
- will-change
- -webkit-overlow-scrolling
4.寫一個正規表示式,滿足一下特點:
-
有8-12位
-
只包含數字和字母
這題呢考察的是正則的使用,答案肯定是不止一種的
[A-Za-z0-9]{8,12}$
/(\d|[A-z]{8,12})/
解析:正則呢,我們需要了解以下幾個元字元,基本寫出來就不難了:
- \d : 匹配一個數字字元,等價於:[0-9]
- {n}: n是非負整數,匹配確定的n次
- {n,} : n是非負整數,至少匹配n次
- {n,m} :n,m均為非負整數,其中n<m,表示最少匹配n次做多匹配m次
- $ : 行尾,匹配輸入的字串結束位置
- [] : (這個是非元字元)表示的是一個範圍
- \ : 將下一個字元標記為一個特殊字元、或一個原義字元、或一個 向後引用、或一個八進位制轉義符
5. IE不支援Function.prototype.bind,自定義函式使IE支援該方法
6. 寫一個sleep函式,sleep(3)等待3秒
該題目的意思就是寫一個sleep函式,設定個時間,等到設定的時間之後再執行
function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } async function demo() { await sleep(3000); //間隔多少毫秒 console.log(new Date()); //修改成要執行的程式碼 } demo();
二面:
二面是技術面,直接會有個技術人員來面試你,主要是問一些原理性和基礎性的東西
1.怎麼實現變數私有化
在ES6之前是沒有塊級作用域之說的,但是可以自己實現,下面給大家寫幾個實現的方法,當然包括ES6的
- ES6的變數申明 let
- 自執行函式
(function Random(){ // 塊級作用域 })()
- 閉包裡面定義的區域性變數
function add() { var num = 10; return function jian() { console.log(num) } } add()(); // 10 console.log(num); // Uncaught ReferenceError: num is not defined
- ES6的Symbol
Symbol是ES6新引入的資料型別,表示獨一無二的值,可以保證不會與其他屬性名產生衝突
Symbol('2')==Symbol("2"); // false var x = y = Symbol('a'); x === y //列印 true 說明該資料型別以引用的方式傳值
下面就用Symbol實現變數私有化
var Person = (function(){ const a = Symbol('a'); const m = Symbol('m'); class Person { constructor(){ this[a] = 'a這是私有變數'; this.b = '變數B-外部可訪問'; this[m] = function(){ console.log('私有方法'); } } getA(){ console.log(this[a]); } getM(){ console.log(this[m]); } } return Person }()) let pc = new Person() console.log(pc)
2. 實現 add(1)(2)(3)=6
這題考察的是柯里化,
3. 實現自適應的方案有哪些?怎麼實現
- 媒體查詢 :根據不同螢幕尺寸寫出不同的適配方案
- flex佈局:設定父元素的display為flex,子元素可以根據需要的佔比來設定flex的值,從而實現自適應佈局
- grid佈局:這是CSS3新提出的,實現方式類似flex,具體看我另外一篇筆記有詳細講解(https://www.cnblogs.com/cythia/p/10894598.html)
- rem:rem是指相對於根元素的字型大小的單位,下面有個公式可以供大家理解
元素的rem值=元素的px/根節點字型大小
var htmlWidth = document.documentElement.clientWidth || document.body.clientWidth //獲取螢幕寬度 var htmlDom = document.getElementsByTagName('html')[0] //獲取html htmlDom.style.fontSize = htmlWidth / 10 + 'px'; //設定html字型大小為螢幕的十分之一 //監聽視窗大小改變 window.addEventListener('resize', () => { var htmlWidth = document.documentElement.clientWidth || document.body.clientWidth var htmlDom = document.getElementsByTagName('html')[0] htmlDom.style.fontSize = htmlWidth / 10 + 'px'; })
當然我們需要考慮一下相容性的問題,大家可以看一下這篇https://github.com/imochen/hotcss文章,上面的這個解決方案是算比較完美了的
- 利用px2rem-loader: 現在我們很多專案都是使用webpack做構建工具,那麼我們可以使用webpack配置px2rem-loader來實現px轉rem
安裝(前提是你已經配置安裝好了css-loader,style-loader或vue-style-loader):
npm install px2rem-loader --save-dev
配置webpack:
{ test: /\.css$/, use: ExtractTextPlugin.extract({ fallback: "style-loader", use: [{ loader: "css-loader", }, { loader: 'px2rem-loader?remUnit=37.5&remPrecision=6' }], }) }
4. vue的怎麼實現效能優化
- vue-router路由懶載入
import Vue from 'vue' import Router from 'vue-router' Vue.use(Router) export default new Router({ mode: 'history', routes: [ { path: '/', component: resolve => require(['@/components/Patient'],resolve), children: [ { path: '', component: resolve => require(['@/components/Hospital'],resolve) }, { path: '*', redirect: '/Hospital' } ] })
- 為item設定唯一的key值:方便vuex的內部機制在迴圈時能夠快速準確的找到該條列表資料
- 減少watch的資料 : 因為當watch的資料比較大的時候,會大量消耗效能,所以 我們可以使用事件中央匯流排或者vuex進行資料的變更操作
- 使用骨架屏載入 : 骨架屏就是在頁面內容未載入完成的時候,先使用一些圖形進行佔位,待內容載入完成後在把它替換掉
- SSR(服務端渲染) : 如果專案比較大的話,首屏無論怎麼優化,都還是會出現閃屏的情況,可以考慮使用SSR
- 按需載入 : 使用第三方的UI框架的時候,如果我們只是使用裡面部分的UI元件的話,只需要匯入需要使用的部分即可
5. webpack怎麼實現效能優化
- 縮小檔案的搜尋範圍 : webpack裡面有個resolve欄位,可以告訴webpack怎麼去搜尋檔案
- 壓縮圖片:
安裝
npm i image-webpack-loader -D
rules: [{ test: /\.(gif|png|jpe?g|svg)$/i, use: [ 'file-loader', { loader: 'image-webpack-loader', options: { bypassOnDebug: true, disable: true, }, }, ], }]
- 壓縮js: 使用webpack內建UglifyJS外掛、ParallelUglifyPlugin
安裝:
npm i -D uglifyjs-webpack-plugin
const UglifyJsPlugin = require('uglifyjs-webpack-plugin') module.exports = { plugins: [ new UglifyJsPlugin() ] }
- 壓縮css:
weboack中4+的版本和以前的版本的壓縮方式是不一樣的,webpack4+版本的方式使用optimize-css-assets-webpack-plugin
安裝
npm install --save-dev optimize-css-assets-webpack-plugin
在webpackconfig中配置:
// 引入模組 const OptimizeCssAssetsPlugin=require('optimize-css-assets-webpack-plugin') plugins: [ new HtmlPlugin({ title:'webpack test', template:path.join(__dirname, './public/index.html') }), // 壓縮css new OptimizeCssAssetsPlugin(), new MiniCssExtractPlugin({ filename:'[name].css', chunkFilename:'[id].css' }) ]
- 去掉不必要的外掛:
- gzip壓縮:
(webpack效能優化請等待我的下一篇筆記)
6. less/sass為什麼巢狀最好不要超過三層
巢狀多層的話,會有以下幾種缺點
- 巢狀多層的話,會降低易讀性,不利於後期的維護
- 巢狀多層的話,權重規則會變得複雜,還要多輸入一些字元,於機器於人都不利
- 效能方面,因為css渲染是由子元素開始父元素上渲染的,如果巢狀多層的,就會一直往上找父元素,這是非常消耗效能的