剛入職半個月,無縫對接的加入了新公司,完美。抽空整理了下最近遇到的面試題,面試公司包括:阿里,騰訊,美的,順豐,平安金服。base是深圳,後三個都比較順利拿到了offer,離大廠還有點差距,加油鴨~
由於是初級前端,面試題可能過於基礎,有錯誤望指出😄。
有些問題當場沒有很全面的答出,後續上網查資料補齊了,可能會有不少雷同,哈哈
有不少題目在這個網站能看到,強推一波:https://muyiy.cn/question/
複製代碼
- BFC 即 Block Formatting Contexts (塊級格式化上下文),是頁面盒模型佈局中的一種 CSS 渲染模式,至關於一個獨立的容器,裏面的元素和外部的元素相互不影響。
- 建立 BFC 的方式有:
html 根元素
float 浮動
position (absolute、fixed)
overflow 除了 visible 之外的值 (hidden、auto、scroll)
display 爲 inline-block、table-cells、flex
複製代碼
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()、instanceof、Array.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()
當檢測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
複製代碼
if (!Array.isArray) {
Array.isArray = function(arg) {
return Object.prototype.toString.call(arg) === '[object Array]';
};
}
複製代碼
4)typeof
typeof 只能檢測基本數據類型,包括boolean、undefined、string、number、symbol,而null、Array、Object ,使用typeof檢測出來都是Object,沒法檢測具體是哪一種引用類型。
複製代碼
<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
複製代碼
從上面這個圖上,咱們能夠看到,瀏覽器渲染過程以下:
一、解析HTML,生成DOM樹,解析CSS,生成CSSOM樹
二、將DOM樹和CSSOM樹結合,生成渲染樹(Render Tree)
三、Layout(迴流):根據生成的渲染樹,進行迴流(Layout),獲得節點的幾何信息(位置,大小)
四、Painting(重繪):根據渲染樹以及迴流獲得的幾何信息,獲得節點的絕對像素
五、Display:將像素髮送給GPU,展現在頁面上。(這一步其實還有不少內容,好比會在GPU將多個合成層合併爲同一個層,並展現在頁面中,而css3硬件加速的原理則是新建合成層)
複製代碼
渲染過程看起來很簡單,讓咱們來具體瞭解下每一步具體作了什麼。
爲了構建渲染樹,瀏覽器主要完成了如下工做:
第一步中,既然說到了要遍歷可見的節點,那麼咱們得先知道,什麼節點是不可見的。不可見的節點包括:
前面咱們經過構造渲染樹,咱們將可見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和樣式的修改,而後一次處理掉。考慮這個例子
const el = document.getElementById('test');
el.style.padding = '5px';
el.style.borderLeft = '1px';
el.style.borderRight = '2px';
複製代碼
例子中,有三個樣式屬性被修改了,每個都會影響元素的幾何結構,引發迴流。固然,大部分現代瀏覽器都對其作了優化,所以,只會觸發一次重排。可是若是在舊版的瀏覽器或者在上面代碼執行的時候,有其餘代碼訪問了佈局信息(上文中的會觸發迴流的佈局信息),那麼就會致使三次重排。
所以,咱們能夠合併全部的改變而後依次處理,好比咱們能夠採起如下的方式:
const el = document.getElementById('test');
el.style.cssText += 'border-left: 1px; border-right: 2px; padding: 5px;';
複製代碼
const el = document.getElementById('test');
el.className += ' active';
複製代碼
<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', 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('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];
複製代碼
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);
複製代碼
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);
複製代碼
var arr = [2,0,1,9,1,0,2,1,4];
var a_arr = [...new Set(arr)]
console.log(a_arr);
複製代碼
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));
複製代碼
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不是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)) {
}
};
複製代碼
便於diff算法的更新,key的惟一性,能讓算法更快的找到須要更新的dom,須要注意的是,key要惟一,否則會出現很隱蔽性的更新問題。
複製代碼
雙向數據綁定是基於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>
複製代碼
處理數據動態變化後,dom還未及時更新的問題。$nextTick就能夠獲取到數據更新後最新的dom變化
複製代碼
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、模塊化和組件化一個最直接的好處就是複用
複製代碼
一、@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方式插入樣式。
複製代碼
var reg = /[^A-Z\d]{15,20}/;
複製代碼
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'
複製代碼
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
複製代碼
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是當即執行,先打印2,3,而後5,再執行then打印4,最後是1
故結果爲:
2,3,5,4,1
複製代碼
前端方面:
1、路由懶加載
2、圖片,資源放cdn
3、頁面圖片較多進行懶加載
4、骨架屏方案
5、採用服務端渲染---nuxt.js
服務器端:
開啓gzip
複製代碼
模型(Model):數據保存
視圖(View):用戶界面。
控制器(Controller):業務邏輯
複製代碼
View 傳送指令到 Controller
Controller 完成業務邏輯後,要求 Model 改變狀態
Model 將新的數據發送到 View,用戶獲得反饋
複製代碼
1. 各部分之間的通訊,都是雙向的。
2. View 與 Model 不發生聯繫,都經過 Presenter 傳遞。
3. View 很是薄,不部署任何業務邏輯,稱爲"被動視圖"(Passive View),即沒有任何主動性,而 Presenter很是厚,全部邏輯都部署在那裏。
複製代碼
View的變更,自動反映在 ViewModel,反之亦然。
複製代碼
1、須要頻繁操做dom
2、容易引發重繪和迴流,影響頁面性能
複製代碼
1、mvvm模式,採用虛擬dom不須要頻繁操做dom,經過雙向綁定,用數據驅動頁面變化,頁面變化對應數據也發生變化,只須要關注數據層的業務邏輯,而無需關注視圖層的更新。能夠儘可能減小無用的更新操做,提升dom渲染效率。
2、組件化開發,頁面由若干個組建組成,可複用性高。
3、社區環境好,各種資源文檔十分齊全。
4、經過Object.defineProperty() 方法,監控對數據的操做,從而能夠自動觸發數據同步。
複製代碼
1、虛擬dom。
2、一切都是組件,組件實例之間能夠嵌套。
3、使用獨特的jsx語法。
複製代碼
1、AngularJS的學習成本高,好比增長了Dependency Injection特性,而Vue.js自己提供的API都比較簡單、直觀。
2、在性能上,AngularJS依賴對數據作髒檢查,因此Watcher越多越慢。
複製代碼
Virtual DOM 能夠理解爲一個簡單的JS對象,而且最少包含標籤名( tag)、屬性(attrs)和子元素對象( children)三個屬性。
複製代碼
優點:
1、具有跨平臺的優點-因爲 Virtual DOM 是以 JavaScript 對象爲基礎而不依賴真實平臺環境,因此使它具備了跨平臺的能力,好比說瀏覽器平臺、Weex、Node 等。
2、提高渲染性能-Virtual DOM的優點不在於單次的操做,而是在大量、頻繁的數據更新下,可以對視圖進行合理、高效的更新。
爲了實現高效的DOM操做,一套高效的虛擬DOM diff算法顯得頗有必要。經過找出本次DOM須要更新的節點來更新,其餘的不更新。
3、是一個js對象,存儲在內存中。
複製代碼
1、Entry:入口,Webpack 執行構建的第一步將從 Entry 開始,可抽象成輸入。
2、Module:模塊,在 Webpack 裏一切皆模塊,一個模塊對應着一個文件。Webpack 會從配置的 Entry 開始遞歸找出全部依賴的模塊。
3、Chunk:代碼塊,一個 Chunk 由多個模塊組合而成,用於代碼合併與分割。
4、Loader:模塊轉換器,用於把模塊原內容按照需求轉換成新內容。
5、Plugin:擴展插件,在 Webpack 構建流程中的特定時機會廣播出對應的事件,插件能夠監聽這些事件的發生,在特定時機作對應的事情。
6、Output:打包後文件輸出的位置。
複製代碼
詳細戳此👇 juejin.im/post/5c3d89…
1、客戶端使用https的url訪問web服務器,要求與服務器創建ssl鏈接
2、web服務器收到客戶端請求後, 會將網站的證書(包含公鑰)傳送一份給客戶端
3、客戶端收到網站證書後會檢查證書的頒發機構以及過時時間, 若是沒有問題就隨機產生一個祕鑰
4、客戶端利用公鑰將會話祕鑰加密, 並傳送給服務端, 服務端利用本身的私鑰解密出會話祕鑰
5、以後服務器與客戶端使用祕鑰加密傳輸
複製代碼
參考出處: muyiy.cn/question/ne…
1、HttpOnly 防止劫取 Cookie
2、輸入檢查-不要相信用戶的全部輸入
3、輸出檢查-存的時候轉義或者編碼
複製代碼
1、驗證碼
2、Referer Check
3、添加token驗證
複製代碼
參考出處: juejin.im/entry/5b4b5…
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]
複製代碼
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: ƒ}
複製代碼