前端面試題整理

前言

剛入職半個月,無縫對接的加入了新公司,完美。抽空整理了下最近遇到的面試題,面試公司包括:阿里,騰訊,美的,順豐,平安金服。base是深圳,後三個都比較順利拿到了offer,離大廠還有點差距,加油鴨~
由於是初級前端,面試題可能過於基礎,有錯誤望指出😄。
有些問題當場沒有很全面的答出,後續上網查資料補齊了,可能會有不少雷同,哈哈
有不少題目在這個網站能看到,強推一波:https://muyiy.cn/question/
複製代碼

一、介紹下 BFC 及其應用

- BFC 即 Block Formatting Contexts (塊級格式化上下文),是頁面盒模型佈局中的一種 CSS 渲染模式,至關於一個獨立的容器,裏面的元素和外部的元素相互不影響。
- 建立 BFC 的方式有:
html 根元素
float 浮動
position (absolute、fixed)
overflow 除了 visible 之外的值 (hidden、auto、scroll)
display 爲 inline-block、table-cells、flex
複製代碼

BFC 特性

1)同一個 BFC 下外邊距會發生摺疊。css

以下例子兩個盒子之間距離只有100px,這不是 CSS 的 bug,咱們能夠理解爲一種規範,若是想要避免外邊距的重疊,能夠將其放在不一樣的 BFC 容器中。html

<head>
    <style> div{ width: 100px; height: 100px; margin: 100px; border: 1px solid red; } </style>
</head>
<body>
    <div></div>
    <div></div>
</body>
複製代碼

便可改爲這樣前端

<head>
    <style> p{ width: 100px; height: 100px; margin: 100px; border: 1px solid red; } div{ overflow: hidden; } </style>
</head>
<body>
    <div>
        <p></p>
    </div>
    <div>
        <p></p>
    </div>
</body>
複製代碼

2)BFC 能夠包含浮動的元素(清除浮動)vue

<head>
    <style> p{ width: 100px; height: 100px; background: black; float: left; } div{ width: 100%; border: 1px solid red; /* 清除浮動 div可包含浮動的元素*/ overflow: hidden; } </style>
</head>
<body>
    <div>
        <p></p>
    </div>
</body>
複製代碼

3)BFC 能夠阻止元素被浮動元素覆蓋react

下面是一個文字環繞效果webpack

<head>
    <style> div{ width: 100px; height: 100px; background: #4CAF50; float: left; } section{ width: 300px; border: 1px solid red; margin: 100px; } </style>
</head>
<body>
    <section>
        <div>我在左邊浮動</div>
        <p>這是一段文字,BFC 即 Block Formatting Contexts (塊級格式化上下文),是頁面盒模型佈局中的一種 CSS 渲染模式,至關於一個獨立的容器,裏面的元素和外部的元素相互不影響。</p>
    </section>
</body>
複製代碼

給p元素添加overflow: hiddencss3

p{
    overflow: hidden;
}
複製代碼

這個方法能夠用來實現兩列自適應佈局,左邊寬度固定,右邊自適應寬度git

二、判斷數組的方法,請分別介紹它們之間的區別和優劣

Object.prototype.toString.call()、instanceofArray.isArray()以及typeof
複製代碼

1)Object.prototype.toString.call()es6

每個繼承 Object 的對象都有 toString 方法,若是 toString 方法沒有重寫的話,會返回 [object type],其中 type 爲對象的類型。但當除了 Object 類型的對象外,其餘類型直接使用 toString 方法時,會直接返回都是內容的字符串,因此咱們須要使用call或者apply方法來改變toString方法的執行上下文。github

const an = ['Hello','World'];
an.toString(); // "Hello,World"
Object.prototype.toString.call(an); // "[object Array]"
複製代碼

這種方法對於全部基本的數據類型都能進行判斷,即便是 null 和 undefined 。 可是沒法區分自定義對象類型,自定義類型能夠採用instanceof區分

console.log(Object.prototype.toString.call("this"));//[object String]
console.log(Object.prototype.toString.call(12));//[object Number]
console.log(Object.prototype.toString.call(true));//[object Boolean]
console.log(Object.prototype.toString.call(undefined));//[object Undefined]
console.log(Object.prototype.toString.call(null));//[object Null]
console.log(Object.prototype.toString.call({name: "this"}));//[object Object]
console.log(Object.prototype.toString.call(function(){}));//[object Function]
console.log(Object.prototype.toString.call([]));//[object Array]
console.log(Object.prototype.toString.call(new Date));//[object Date]
console.log(Object.prototype.toString.call(/\d/));//[object RegExp]
function Person(){};
console.log(Object.prototype.toString.call(new Person));//[object Object]
複製代碼

Object.prototype.toString.call() 經常使用於判斷瀏覽器內置對象。

2)instanceof

instanceof 的內部機制是經過判斷對象的原型鏈中是否是能找到類型的 prototype。

使用 instanceof判斷一個對象是否爲數組,instanceof 會判斷這個對象的原型鏈上是否會找到對應的 Array 的原型,找到返回 true,不然返回 false。

但 instanceof 只能用來判斷對象類型,原始類型不能夠。而且全部對象類型 instanceof Object 都是 true。

instanceof Array; // true
instanceof Object; // true
'a' instanceof String; //false
複製代碼

3)Array.isArray()

  • 功能:用來判斷對象是否爲數組
  • instanceof 與 isArray

當檢測Array實例時,Array.isArray 優於 instanceof ,由於 Array.isArray 能夠檢測出 iframes

var iframe = document.createElement('iframe');
document.body.appendChild(iframe);
xArray = window.frames[window.frames.length-1].Array;
var arr = new xArray(1,2,3); // [1,2,3]

// Correctly checking for Array
Array.isArray(arr);  // true
Object.prototype.toString.call(arr); // true
// Considered harmful, because doesn't work though iframes
arr instanceof Array; // false
複製代碼
  • Array.isArray() 與 Object.prototype.toString.call()
    Array.isArray()是ES5新增的方法,當不存在 Array.isArray() ,能夠用 Object.prototype.toString.call() 實現。
if (!Array.isArray) {
    Array.isArray = function(arg) {
        return Object.prototype.toString.call(arg) === '[object Array]';
    };
}
複製代碼

4)typeof

typeof 只能檢測基本數據類型,包括boolean、undefined、string、number、symbol,而nullArrayObject ,使用typeof檢測出來都是Object,沒法檢測具體是哪一種引用類型。
複製代碼

三、怎麼讓一個div水平垂直居中

<div class="parent">
    <div class="child"></div>
</div>
複製代碼

1)使用position + transform,不定寬高時

.parent{
    position: relative;
}
.child{
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%,-50%);
}
複製代碼

2)使用position + transform,有寬高時

.parent{
    position: relative;
}
.child{
    width: 100px;
    height: 100px;
    position: absolute;
    left: 50%;
    top: 50%;
    margin-left: -50px;
    margin-top: -50px;
}
複製代碼

3)使用flex

.parent{
    display: flex;
    align-items: center;
    justify-content: center;
}
複製代碼

或者

.parent{
    display: flex;
    align-items: center;
}
.child{
    margin: 0 auto;
}
複製代碼

或者

.parent{
    display: flex;
}
.child{
    margin: auto;
}
複製代碼

4)使用position

.parent{
    position: relative;
}
.child{
    position: absolute;
    left: 0;
    top: 0;
    right: 0;
    bottom: 0;
    margin: auto;
}
複製代碼

5)使用grid

.parent{
    display: grid;
}
.child{
    justify-self: center;
    align-self: center;
}
複製代碼

6)使用table

.parent{
    display: table;
}
.child{
    display: table-cell;
    vertical-align: middle;
    text-align: center;
}
複製代碼

或者

.parent {
    display: table-cell;
    text-align: center;
    vertical-align: middle;
}
.child {
    display: inline-block;
}
複製代碼

7)使用僞類

.parent{
    font-size: 0;
    text-align: center;
}
.parent::before {
    content: "";
    display: inline-block;
    width: 0;
    height: 100%;
    vertical-align: middle;
}
.child{
    display: inline-block;
    vertical-align: middle;
}
複製代碼

四、下面的代碼打印什麼內容,爲何?

var b = 10;
(function b(){
    b = 20;
    console.log(b); 
})();
複製代碼

正常模式下:

var b = 10;
(function b() {
   // 內部做用域,會先去查找是有已有變量b的聲明,有就直接賦值20,確實有了呀。發現了具名函數 function b(){},拿此b作賦值;
   // IIFE的函數沒法進行賦值(內部機制,相似const定義的常量),因此無效。
  // (這裏說的「內部機制」,想搞清楚,須要去查閱一些資料,弄明白IIFE在JS引擎的工做方式,堆棧存儲IIFE的方式等)
    b = 20;
    console.log(b); // [Function b]
    console.log(window.b); // 10,不是20
})();
複製代碼

嚴格模式下會報錯:

var b = 10;
(function b() {
 'use strict'
  b = 20;
  console.log(b)
})() // "Uncaught TypeError: Assignment to constant variable."
複製代碼

有window:

var b = 10;
(function b() {
    window.b = 20; 
    console.log(b); // [Function b]
    console.log(window.b); // 20是必然的
})();
複製代碼

有var:

var b = 10;
(function b() {
    var b = 20; // IIFE內部變量
    console.log(b); // 20
   console.log(window.b); // 10 
})();
複製代碼

五、下面的代碼打印什麼內容,爲何?

var a = 10;
(function () {
    console.log(a)
    a = 5
    console.log(window.a)
    var a = 20;
    console.log(a)
})()
複製代碼

先說結果

依次爲:undefined,10,20

var a = 10;
(function () {
    //函數裏面從新定義了a,變量提高,預解析
    console.log(a);//undefined
    a = 5;
    console.log(window.a);//10,a是函數局部變量
    var a = 20;
    console.log(a);//固然20
})()
console.log(a);//10,至關於window.a
複製代碼

換成這樣:

var a = 10;
(function () {
    //函數裏面沒有從新定義
    console.log(a);//10
    a = 5;
    console.log(window.a);//5
    a = 20;
    console.log(a);//固然20
})()
console.log(a);//20,至關於window.a
複製代碼

換成這樣:

var a = 10;
function b() {
    //函數裏面從新定義了a,變量提高,預解析
    console.log(a);//undefined
    a = 5;
    console.log(window.a);//10,a是函數局部變量
    var a = 20;
    console.log(a);//固然20
}
b();
console.log(a);//10,至關於window.a
複製代碼

六、簡單介紹下重繪和迴流(Repaint & Reflow),以及如何進行優化

先來看下瀏覽器的渲染過程

從上面這個圖上,咱們能夠看到,瀏覽器渲染過程以下:

一、解析HTML,生成DOM樹,解析CSS,生成CSSOM樹
二、將DOM樹和CSSOM樹結合,生成渲染樹(Render Tree)
三、Layout(迴流):根據生成的渲染樹,進行迴流(Layout),獲得節點的幾何信息(位置,大小)
四、Painting(重繪):根據渲染樹以及迴流獲得的幾何信息,獲得節點的絕對像素
五、Display:將像素髮送給GPU,展現在頁面上。(這一步其實還有不少內容,好比會在GPU將多個合成層合併爲同一個層,並展現在頁面中,而css3硬件加速的原理則是新建合成層)
複製代碼

渲染過程看起來很簡單,讓咱們來具體瞭解下每一步具體作了什麼。

生成渲染樹

爲了構建渲染樹,瀏覽器主要完成了如下工做:

  1. 從DOM樹的根節點開始遍歷每一個可見節點。
  2. 對於每一個可見的節點,找到CSSOM樹中對應的規則,並應用它們。
  3. 根據每一個可見節點以及其對應的樣式,組合生成渲染樹。

第一步中,既然說到了要遍歷可見的節點,那麼咱們得先知道,什麼節點是不可見的。不可見的節點包括:

  • 一些不會渲染輸出的節點,好比script、meta、link等。
  • 一些經過css進行隱藏的節點。好比display:none。注意,利用visibility和opacity隱藏的節點,仍是會顯示在渲染樹上的。只有display:none的節點纔不會顯示在渲染樹上。

注意:渲染樹只包含可見的節點

迴流

前面咱們經過構造渲染樹,咱們將可見DOM節點以及它對應的樣式結合起來,但是咱們還須要計算它們在設備視口(viewport)內的確切位置和大小,這個計算的階段就是迴流。

爲了弄清每一個對象在網站上的確切大小和位置,瀏覽器從渲染樹的根節點開始遍歷,咱們能夠如下面這個實例來表示:

<!DOCTYPE html>
<html>
    <head>
        <meta name="viewport" content="width=device-width,initial-scale=1">
        <title>Critial Path: Hello world!</title>
    </head>
    <body>
        <div style="width: 50%">
        <div style="width: 50%">Hello world!</div>
        </div>
    </body>
</html>
複製代碼

咱們能夠看到,第一個div將節點的顯示尺寸設置爲視口寬度的50%,第二個div將其尺寸設置爲父節點的50%。而在迴流這個階段,咱們就須要根據視口具體的寬度,將其轉爲實際的像素值。

重繪

最終,咱們經過構造渲染樹和迴流階段,咱們知道了哪些節點是可見的,以及可見節點的樣式和具體的幾何信息(位置、大小),那麼咱們就能夠將渲染樹的每一個節點都轉換爲屏幕上的實際像素,這個階段就叫作重繪節點。

既然知道了瀏覽器的渲染過程後,咱們就來探討下,什麼時候會發生迴流重繪。

什麼時候發生迴流重繪

咱們前面知道了,迴流這一階段主要是計算節點的位置和幾何信息,那麼當頁面佈局和幾何信息發生變化的時候,就須要迴流。好比如下狀況:

  • 添加或刪除可見的DOM元素
  • 元素的位置發生變化
  • 元素的尺寸發生變化(包括外邊距、內邊框、邊框大小、高度和寬度等)
  • 內容發生變化,好比文本變化或圖片被另外一個不一樣尺寸的圖片所替代。
  • 頁面一開始渲染的時候(這確定避免不了)
  • 瀏覽器的窗口尺寸變化(由於迴流是根據視口的大小來計算元素的位置和大小的)

注意:迴流必定會觸發重繪,而重繪不必定會迴流

根據改變的範圍和程度,渲染樹中或大或小的部分須要從新計算,有些改變會觸發整個頁面的重排,好比,滾動條出現的時候或者修改了根節點。

瀏覽器的優化機制

現代的瀏覽器都是很聰明的,因爲每次重繪都會形成額外的計算消耗,所以大多數瀏覽器都會經過隊列化修改並批量執行來優化重繪過程。瀏覽器會將修改操做放入到隊列裏,直到過了一段時間或者操做達到了一個閾值,才清空隊列。可是!當你獲取佈局信息的操做的時候,會強制隊列刷新,好比當你訪問如下屬性或者使用如下方法:

  • offsetTop、offsetLeft、offsetWidth、offsetHeight
  • scrollTop、scrollLeft、scrollWidth、scrollHeight
  • clientTop、clientLeft、clientWidth、clientHeight
  • getComputedStyle()
  • getBoundingClientRect
  • 具體能夠訪問這個網站:gist.github.com/paulirish/5…

以上屬性和方法都須要返回最新的佈局信息,所以瀏覽器不得不清空隊列,觸發迴流重繪來返回正確的值。所以,咱們在修改樣式的時候,最好避免使用上面列出的屬性,他們都會刷新渲染隊列。若是要使用它們,最好將值緩存起來。

減小回流和重繪

好了,到了咱們今天的重頭戲,前面說了這麼多背景和理論知識,接下來讓咱們談談如何減小回流和重繪。

最小化重繪和重排

因爲重繪和重排可能代價比較昂貴,所以最好就是能夠減小它的發生次數。爲了減小發生次數,咱們能夠合併屢次對DOM和樣式的修改,而後一次處理掉。考慮這個例子

const el = document.getElementById('test');
el.style.padding = '5px';
el.style.borderLeft = '1px';
el.style.borderRight = '2px';
複製代碼

例子中,有三個樣式屬性被修改了,每個都會影響元素的幾何結構,引發迴流。固然,大部分現代瀏覽器都對其作了優化,所以,只會觸發一次重排。可是若是在舊版的瀏覽器或者在上面代碼執行的時候,有其餘代碼訪問了佈局信息(上文中的會觸發迴流的佈局信息),那麼就會致使三次重排。

所以,咱們能夠合併全部的改變而後依次處理,好比咱們能夠採起如下的方式:

  • 使用cssText
    const el = document.getElementById('test');
    el.style.cssText += 'border-left: 1px; border-right: 2px; padding: 5px;';
    複製代碼
  • 修改CSS的class
    const el = document.getElementById('test');
    el.className += ' active';
    複製代碼

具體參考:muyiy.cn/question/br…

七、文字兩端對齊

<div>姓名</div>
<div>手機號碼</div>
<div>帳號</div>
<div>密碼</div>
複製代碼
div {
    margin: 10px 0; 
    width: 100px;
    border: 1px solid red;
    text-align: justify;
    text-align-last: justify;
}
複製代碼

八、['1', '2', '3'].map(parseInt)的結果是什麼?

先說結果:
['1', NaN, NaN]
爲何不是['1', '2', '3']呢,下面開始分析
複製代碼
  • map() 方法返回一個新數組,數組中的元素爲原始數組元素調用函數處理後的值。

  • map() 方法按照原始數組元素順序依次處理元素。

map(parseInt)實際上是:

map(function(item, index){
    return parseInt(item, index);
})
複製代碼

即依次運行的是:

parseInt('1', 0);
parseInt('2', 1);
parseInt('3', 2);
複製代碼

parseInt的用法

  • parseInt(string, radix) 函數可解析一個字符串,並返回一個整數。
  • 當參數 radix 的值爲 0,或沒有設置該參數時,parseInt() 會根據 string 來判斷數字的基數。
  • radix 可選。表示要解析的數字的基數。該值介於 2 ~ 36 之間。

因此: parseInt('1', 0);//'1' parseInt('2', 1);//NaN parseInt('3', 2);//NaN,因爲2進制中沒有3

九、寫出以下代碼的打印結果

function changeObjProperty(o) {
    o.siteUrl = "http://www.baidu.com";
    o = new Object();
    o.siteUrl = "http://www.google.com";
} 
let webSite = new Object();
changeObjProperty(webSite);
console.log(webSite.siteUrl);
複製代碼

此題咋看小問題,其實暗藏玄機。 先說答案:

console.log(webSite.siteUrl);//"http://www.baidu.com"
複製代碼

覆盤以下:

function changeObjProperty(o) {
    //o是形參,對象的引用,依舊指向原地址,至關於 var o = webSite;賦值改變對象的屬性
    o.siteUrl = "http://www.baidu.com";
    //變量o指向新的地址 之後的變更和舊地址無關,題目打印的是外部webSite.siteUrl
    o = new Object();
    o.siteUrl = "http://www.google.com";
}
複製代碼

將題目改爲以下:

function changeObjProperty(o) {
    o.siteUrl = "http://www.baidu.com";
    o = new Object();
    o.siteUrl = "http://www.google.com";
    return o;
} 
let webSite = new Object();
changeObjProperty(webSite);
console.log(webSite.siteUrl);
let newSite = changeObjProperty(webSite);
console.log(newSite.siteUrl);
複製代碼

此時打印結果以下:

console.log(webSite.siteUrl);//"http://www.baidu.com"
console.log(newSite.siteUrl);//"http://www.google.com"
複製代碼

十、數組去重

var arr = [2,0,1,9,1,0,2,1];
複製代碼
  • indexOf
var arr = [2,0,1,9,1,0,2,1];
var a_arr = [];
for(let i=0;i<arr.length;i++){
    if(a_arr.indexOf(arr[i]) == -1){
        a_arr.push(arr[i]);
    }
}
console.log(a_arr);
複製代碼
  • 兩個for循環
var arr = [2,0,1,9,1,0,2,1,4];
var a_arr = [];
for(let i=0;i<arr.length;i++){
    var flag = true;
    for(let j=0;j<a_arr.length;j++){
        if(arr[i] == arr[j]){
            flag = false;
        }
    }
    if(flag){
        a_arr.push(arr[i]);
    }
}
console.log(a_arr);
複製代碼
  • ES6 set方法
var arr = [2,0,1,9,1,0,2,1,4];
var a_arr = [...new Set(arr)]
console.log(a_arr);
複製代碼
  • filter方法
var arr = [2,0,1,9,1,0,2,1,4];
function unique(array) {
    var res = array.filter(function(item, index, array){
        return array.indexOf(item) === index;
    })
    return res;
}
console.log(unique(arr));
複製代碼

十一、 一個頁面從輸入 URL 到頁面加載顯示完成,這個過程當中都發生了什麼?

1、瀏覽器會開啓一個線程來處理這個請求,對 URL 分析判斷若是是 http 協議就按照 Web 方式來處理;
2、調用瀏覽器內核中的對應方法,好比 WebView 中的 loadUrl 方法;
3、經過DNS解析獲取網址的IP地址,設置 UA 等信息發出第二個GET請求;
4、進行HTTP協議會話,客戶端發送報頭(請求報頭);
5、進入到web服務器上的 Web Server,如 Apache、Tomcat、Node.JS 等服務器;
6、進入部署好的後端應用,如 PHP、Java、JavaScript、Python 等,找到對應的請求處理;
7、處理結束回饋報頭,此處若是瀏覽器訪問過,緩存上有對應資源,會與服務器最後修改時間對比,一致則返回304;
8、瀏覽器開始下載html文檔(響應報頭,狀態碼200),同時使用緩存;
9、文檔樹創建,根據標記請求所需指定MIME類型的文件(好比css、js),同時設置了cookie;
10、頁面開始渲染DOM,JS根據DOM API操做DOM,執行事件綁定等,頁面顯示完成。

複製代碼

十二、ajax實現原理及方法使用

AJAX不是JavaScript的規範,它來自一個縮寫:Asynchronous JavaScript and XML,意思就是用JavaScript執行異步網絡請求。
複製代碼

原生ajax的請求步驟

//建立 XMLHttpRequest 對象
var ajax = new XMLHttpRequest();
//規定請求的類型、URL 以及是否異步處理請求。
ajax.open('GET',url,true);
//發送信息至服務器時內容編碼類型
ajax.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); 
//發送請求
ajax.send(null);  
//接受服務器響應數據
ajax.onreadystatechange = function () {
    if (obj.readyState == 4 && (obj.status == 200 || obj.status == 304)) { 
    }
};
複製代碼

1三、說說vue中key的原理

便於diff算法的更新,key的惟一性,能讓算法更快的找到須要更新的dom,須要注意的是,key要惟一,否則會出現很隱蔽性的更新問題。
複製代碼

1四、vue雙向綁定的原理是什麼?

雙向數據綁定是基於Object.defineProperty()從新定義get和set方法實現的。修改觸發set方法賦值,獲取觸發get方法取值,並經過數據劫持發佈信息。
複製代碼
let obj = {
    name: 't-one',
    location: {x: 100, y: 200}
}

function render(){
    console.log('渲染視圖');
}

function observe(data){
    for(let key in data){
        defineData(data, key, data[key]);
    }
}

function defineData(data, key, value){
    Object.defineProperty(data, key, {
        get(){
            return value;
        },
        set(newValue){
            render();
            value = newValue;
        }
    })
}
observe(obj);
obj.name = 'liu';
console.log(obj.name);//liu
複製代碼

一個簡易的雙向綁定

<input type="text" id="input">
<div id="content"></div>
<script>
    function obersver(data){
        for(let i in data){
            defineData(data,i,data[i]);
        }
    }
    function defineData(data,key,value){
        Object.defineProperty(data,key,{
            get:function(){
                return value;
            },
            set: function(newValue){
                console.log('調用了set====');
                value = newValue;
                document.getElementById('content').innerHTML = newValue;
            }
        })
    }
    let obj = {};
    document.addEventListener('keyup',function(e){
        obersver(obj);
        obj.text = e.target.value;
        console.log(obj.text);
    })
</script>
複製代碼

1五、vue中$nextTick有什麼做用?

處理數據動態變化後,dom還未及時更新的問題。$nextTick就能夠獲取到數據更新後最新的dom變化
複製代碼

1六、淺談前端工程化、模塊化、組件化

前端工程化

1、將前端項目當成一項系統工程進行分析、組織和構建從而達到項目結構清晰、分工明確、團隊配合默契、開發效率提升的目的
2、工程化思惟就是「結構、樣式和動做分離」。如目錄分爲assets,components,router,util
複製代碼

前端模塊化

1、能夠簡單的認爲模塊化和組件化是工程化的表現形式
2、JS模塊化方案不少有AMD/CommonJS/UMD/ES6 Module等,CSS模塊化開發大可能是在less、sass、stylus
複製代碼

es6帶來了語言原生的模塊化方案:

const methodOne = params => {
    console.log(params)
}
const methodTwo = params => {
    console.log(params)
}
// 導出方式 1
export default {
    methodOne,
    methodTwo
}
// 導出方式 2 
export {
    methodOne,
    methodTwo
}
複製代碼
// 引入方式 1 對應導出方式 1
import module from './module'
module.methodOne();

// 引入方式2 對應導出方式 2
import { methodOne } from './module'
methodOne();
複製代碼

前端組件化

1、組件化將頁面視爲一個容器,頁面上各個獨立部分例如:頭部、導航、焦點圖、側邊欄、底部等視爲獨立組件,不一樣的頁面根據內容的須要,去盛放相關組件便可組成完整的頁面。
2、模塊化和組件化一個最直接的好處就是複用
複製代碼

1七、css中link與@import的區別

一、@import是 CSS 提供的語法規則,只有導入樣式表的做用;link是HTML提供的標籤,不只能夠加載 CSS 文件,還能夠定義 RSS、rel 鏈接屬性等。
2、加載頁面時,link引入的CSS被同時加載,@import引入的CSS將在頁面加載完畢後加載。
3、link標籤做爲HTML元素,不存在兼容性問題,而@import是CSS2.1纔有的語法,故老版本瀏覽器(IE5以前)不能識別。
4、能夠經過JS操做DOM,來插入link標籤改變樣式;因爲DOM方法是基於文檔的,沒法使用@import方式插入樣式。
複製代碼

1八、請寫一個正則15-20位的大寫字母或數字

var reg = /[^A-Z\d]{15,20}/;
複製代碼

1九、以下代碼輸出是什麼

var fullName = 'a';
var obj = {
    fullName: 'b',
    prop:{
        fullName: 'c',
        getFullName: function(){
            console.log(this);
            return this.fullName
        }
    }
}
console.log(obj.prop.getFullName());
var test = obj.prop.getFullName;
console.log(test());
複製代碼

解釋以下:

obj.prop.getFullName()這裏this指向obj.prop,故
console.log(obj.prop.getFullName());//'c'
test = obj.prop.getFullName;此處this指向window,故
console.log(test());//'a'
複製代碼

20、以下代碼輸出是什麼

var num = 1;
var myObject = {
    num: 2,
    add: function() {
        this.num = 3;
        (function() {
            console.log(this.num);
            this.num = 4;
        })();
        console.log(this.num);
    },
    sub: function() {
        console.log(this.num)
    }
}
myObject.add();
console.log(myObject.num);
console.log(num);
var sub = myObject.sub;
sub();
複製代碼

解釋以下:

var num = 1;
var myObject = {
    num: 2,
    add: function() {
        this.num = 3;
        (function() {
            //此時this指向window,故值爲1
            console.log(this.num);
            //此時window.num = 4
            this.num = 4;
        })();
        //此處this爲myObject,故this.num=3
        console.log(this.num);
    },
    sub: function() {
        console.log(this.num)
    }
}
myObject.add();//1,3
console.log(myObject.num);//3
console.log(num);//4
//此處this指向window
var sub = myObject.sub;
sub();//4
複製代碼

2一、以下代碼輸出的是什麼

setTimeout(function(){
    console.log(1)
}, 0)
new Promise(function executor(resolve){
    console.log(2);
    for(var i=0;i<100;i++){
        i==99 && resolve();
    }
    console.log(3);
}).then(function(){
    console.log(4);
});
console.log(5);
複製代碼

解釋以下:

setTimeout 和 setInterval的運行機制是將指定的代碼移出本次執行,等到下一輪 Event Loop 時,再檢查是否到了指定時間。若是到了,就執行對應的代碼;若是不到,就等到再下一輪 Event Loop時從新判斷。
這意味着,setTimeout指定的代碼,必須等到本次執行的全部同步代碼都執行完,纔會執行。
故最後輸出1
new Promise是當即執行,先打印23,而後5,再執行then打印4,最後是1
故結果爲:
23541
複製代碼

2二、vue項目優化的手段有哪些

前端方面:
1、路由懶加載
2、圖片,資源放cdn
3、頁面圖片較多進行懶加載
4、骨架屏方案
5、採用服務端渲染---nuxt.js
服務器端:
開啓gzip
複製代碼

2三、mvc,mvp,mvvm是什麼

mvc

模型(Model):數據保存
視圖(View):用戶界面。
控制器(Controller):業務邏輯
複製代碼

全部通訊都是單向的

View 傳送指令到 Controller
Controller 完成業務邏輯後,要求 Model 改變狀態
Model 將新的數據發送到 View,用戶獲得反饋
複製代碼

mvp

1. 各部分之間的通訊,都是雙向的。
2. View 與 Model 不發生聯繫,都經過 Presenter 傳遞。
3. View 很是薄,不部署任何業務邏輯,稱爲"被動視圖"(Passive View),即沒有任何主動性,而 Presenter很是厚,全部邏輯都部署在那裏。
複製代碼

mvvm

View的變更,自動反映在 ViewModel,反之亦然。
複製代碼

2四、vue,jq,react,angular區別,各自優點

jq

1、須要頻繁操做dom
2、容易引發重繪和迴流,影響頁面性能
複製代碼

vue

1、mvvm模式,採用虛擬dom不須要頻繁操做dom,經過雙向綁定,用數據驅動頁面變化,頁面變化對應數據也發生變化,只須要關注數據層的業務邏輯,而無需關注視圖層的更新。能夠儘可能減小無用的更新操做,提升dom渲染效率。
2、組件化開發,頁面由若干個組建組成,可複用性高。
3、社區環境好,各種資源文檔十分齊全。
4、經過Object.defineProperty() 方法,監控對數據的操做,從而能夠自動觸發數據同步。
複製代碼

react

1、虛擬dom。
2、一切都是組件,組件實例之間能夠嵌套。
3、使用獨特的jsx語法。
複製代碼

angular

1、AngularJS的學習成本高,好比增長了Dependency Injection特性,而Vue.js自己提供的API都比較簡單、直觀。
2、在性能上,AngularJS依賴對數據作髒檢查,因此Watcher越多越慢。
複製代碼

2五、什麼是虛擬dom,優點是什麼,存儲在哪

Virtual DOM 能夠理解爲一個簡單的JS對象,而且最少包含標籤名( tag)、屬性(attrs)和子元素對象( children)三個屬性。
複製代碼

優點:

1、具有跨平臺的優點-因爲 Virtual DOM 是以 JavaScript 對象爲基礎而不依賴真實平臺環境,因此使它具備了跨平臺的能力,好比說瀏覽器平臺、Weex、Node 等。

2、提高渲染性能-Virtual DOM的優點不在於單次的操做,而是在大量、頻繁的數據更新下,可以對視圖進行合理、高效的更新。
爲了實現高效的DOM操做,一套高效的虛擬DOM diff算法顯得頗有必要。經過找出本次DOM須要更新的節點來更新,其餘的不更新。
3、是一個js對象,存儲在內存中。
複製代碼

2六、談談webpack的理解

1、Entry:入口,Webpack 執行構建的第一步將從 Entry 開始,可抽象成輸入。
2、Module:模塊,在 Webpack 裏一切皆模塊,一個模塊對應着一個文件。Webpack 會從配置的 Entry 開始遞歸找出全部依賴的模塊。
3、Chunk:代碼塊,一個 Chunk 由多個模塊組合而成,用於代碼合併與分割。
4、Loader:模塊轉換器,用於把模塊原內容按照需求轉換成新內容。
5、Plugin:擴展插件,在 Webpack 構建流程中的特定時機會廣播出對應的事件,插件能夠監聽這些事件的發生,在特定時機作對應的事情。
6、Output:打包後文件輸出的位置。
複製代碼

2七、談談event loop

詳細戳此👇 juejin.im/post/5c3d89…

2八、介紹 HTTPS 握手過程

1、客戶端使用https的url訪問web服務器,要求與服務器創建ssl鏈接
2、web服務器收到客戶端請求後, 會將網站的證書(包含公鑰)傳送一份給客戶端
3、客戶端收到網站證書後會檢查證書的頒發機構以及過時時間, 若是沒有問題就隨機產生一個祕鑰
4、客戶端利用公鑰將會話祕鑰加密, 並傳送給服務端, 服務端利用本身的私鑰解密出會話祕鑰
5、以後服務器與客戶端使用祕鑰加密傳輸
複製代碼

參考出處: muyiy.cn/question/ne…

2九、如何防範CSRF攻擊,XSS攻擊

XSS攻擊的防範

1、HttpOnly 防止劫取 Cookie
2、輸入檢查-不要相信用戶的全部輸入
3、輸出檢查-存的時候轉義或者編碼
複製代碼

CSRF攻擊的防範

1、驗證碼
2、Referer Check
3、添加token驗證
複製代碼

參考出處: juejin.im/entry/5b4b5…

30、使用 sort() 對數組 [3, 15, 8, 29, 102, 22] 進行排序,輸出結果

var arr = [3,15,8,29,102,22]
複製代碼

a、直接使用sort()方法,默認的排序方法會將數組元素轉換爲字符串,而後比較字符串中字符的UTF-16編碼順序來進行排序。

var brr = arr.sort();
console.log(brr);//[102,15,22,29,3,8]
複製代碼

b、sort,能夠接收一個函數,返回值是比較兩個數的相對順序的值

var brr = arr.sort((a,b)=>a-b);
console.log(brr);//[3, 8, 15, 22, 29, 102]
複製代碼
  • 返回值大於0 即a-b > 0 , a 和 b 交換位置
  • 返回值大於0 即a-b < 0 , a 和 b 位置不變
  • 返回值等於0 即a-b = 0 , a 和 b 位置不變

3一、箭頭函數與普通函數的區別

function data(a,b){
    return a-b
};

var data = (a,b)=>a-b;
複製代碼

a、箭頭函數是匿名函數,不能做爲構造函數,不能使用new

let FunConstructor = () => {
    console.log('lll');
}

let fc = new FunConstructor();//報錯
複製代碼

b、箭頭函數不綁定arguments,取而代之用rest參數...解決

function A(a){
    console.log(arguments);
}
A(1,2,3,4,5,8);  // [1, 2, 3, 4, 5, 8, callee: ƒ, Symbol(Symbol.iterator): ƒ]

let B = (b)=>{
    console.log(arguments);
}

B(2,92,32,32);   // Uncaught ReferenceError:arguments is not defined

let C = (...c) => {
    console.log(c);
}
C(3,82,32,11323);  // [3, 82, 32, 11323]
複製代碼

c、箭頭函數不綁定this,會捕獲其所在的上下文的this值,做爲本身的this值

var obj = {
    a: 10,
    b: () => {
        console.log(this.a); // undefined
        console.log(this); // Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, …}
    },
    c: function() {
        console.log(this.a); // 10
        console.log(this); // {a: 10, b: ƒ, c: ƒ}
    }
}
obj.b(); 
obj.c();
複製代碼

d、箭頭函數經過call()或apply()方法調用一個函數時,只傳入了一個參數,對 this 並無影響。

let obj2 = {
    a: 10,
    b: function(n) {
        let f = (n) => n + this.a;
        return f(n);
    },
    c: function(n) {
        let f = (n) => n + this.a;
        let m = {
            a: 20
        };
        return f.call(m,n);
    }
};
console.log(obj2.b(1));  // 11
console.log(obj2.c(1)); // 11
複製代碼

e、箭頭函數沒有原型屬性

var a = ()=>{
    return 1;
}

function b(){
    return 2;
}

console.log(a.prototype);  // undefined
console.log(b.prototype);   // {constructor: ƒ}
複製代碼

原文地址:github.com/liujianxi/s…

相關文章
相關標籤/搜索