web能夠簡單分爲:結構、表現、行爲。三部分獨立開來使其模塊化
w3c是對web作出規範,使代碼更嚴謹,作出來的網頁更易使用,維護。
w3c作出的規範可分爲以下:
結構上:(標籤規範對頁面的搜索權重有很大關係,寫的越規範網站在搜索排名越靠前)javascript
表現、行爲上:php
發送機制css
一、get請求會將參數跟在URL後面進行參數傳遞,而post請求則是做爲http消息的實體內容發送給web服務器;
二、get提交的數據限制是1024字節,這種顯示是來自特定瀏覽器和服務器對它的限制。如ie的URL長度限制是2083字節,火狐理論上沒有長度限制。注意這個限制是URL 的整個長度,而不是參數的長度。
三、get方式請求的數據會被瀏覽器緩存起來。由於其餘人能夠從瀏覽器的歷史記錄中讀取到這些數據,好比:帳號或者密碼等。在某種狀況下,get方式會帶來嚴重的安全問題,而post相對來講能夠避免這些問題。html
在服務端的區別前端
一、客戶端請求使用get時,服務端使用Request.QueryString來獲取,而客戶端使用post請求時,服務端使用Request.Form來獲取。
二、post用於建立資源,資源的內容會被編入http請示的內容中,例如,處理定貨表單等。
三、當請求無反作用時(如進行搜索),使用get方法,當請求有反作用時(如添加數據),則用post方法。vue
1. 文件合併
2. 文件最小化/文件壓縮
3. 使用 CDN 託管
4. 緩存的使用(多個域名來提供緩存)
5. 其餘java
「官方」的解釋是:所謂「閉包」,指的是一個擁有許多變量和綁定了這些變量的環境的表達式(一般是一個函數),於是這些變量也是該表達式的一部分。webpack
通俗的講:就是函數a的內部函數b,被函數a外部的一個變量引用的時候,就建立了一個閉包。web
閉包的特性:面試
①.封閉性:外界沒法訪問閉包內部的數據,若是在閉包內聲明變量,外界是沒法訪問的,除非閉包主動向外界提供訪問接口;
②.持久性:通常的函數,調用完畢以後,系統自動註銷函數,而對於閉包來講,在外部函數被調用以後,閉包結構依然保存在
系統中,閉包中的數據依然存在,從而實現對數據的持久使用。
優勢:
① 減小全局變量。
② 減小傳遞函數的參數量
③ 封裝;
缺點:
使用閉包會佔有內存資源,過多的使用閉包會致使內存溢出等.
在https頁面下的帶有相對路徑的請求都會與頁面的協議保持一致。若是想在https頁面下發送http的請求,若是隻把連接寫死成爲http的絕對路徑是不夠的,這樣會致使http的請求與總頁面https的請求的session不一致。
爲何呢?緣由是https的請求中服務器發回的cookie是標記爲"secure"的,而http的請求時非"secure","因爲在服務器端secure"的cookie不會兼容非"secure"的,因此當http的請求攜帶着同一jsessionid的cookie到達服務器時,服務器拒絕非"secure",進而返回的結果是一個新的非"secure"的cookie,因而兩個session就不一樣了。
怎麼解決呢?由緣由分析可知,兩個session不一樣,更具體說是cookie的狀態不一樣。那麼辦法是,在接收到第一個https請求的響應後 到 發送下面的http請求以前,將cookie去"secure"狀態,可是又要保證jsessionid不變。具體操做能夠新建一個cookie(新建的是非"secure"狀態),而後賦予同一個jessionid,而後加入response中。
推薦文章:傳送門
人家講得已經很清楚了,案例跟優缺點都整理出來了,推薦閱讀
一、建立ajax對象(XMLHttpRequest/ActiveXObject(Microsoft.XMLHttp))
二、打開連接 open(請求方式,'請求路徑',同步/異步)
三、發送 send()
四、當ajax對象完成第四步(onreadystatechange)數據接收完成,判斷對象狀態碼(readystate) 4 HTTP響應徹底接收 在判斷http響應狀態(status)200-300之間或者304(緩存)執行回調函數 獲取的數據轉成字符串格式(responseText)
具體代碼參考網上...
console.log('script start'); setTimeout(() => { console.log('setTimeout'); },0) Promise.resolve().then(function() { console.log('promise1'); }).then(function() { console.log('promise2'); }); console.log('script end')
考察的是代碼執行順序問題,定時器和主程序屬於宏任務,Promise中then的回調屬於微任務,在每一個宏任務裏面都會先執行完微任務再去執行下一個宏任務。
本題執行邏輯應該是主線程中console.log('script start');碰到定時器,把這個宏任務扔事件隊列裏面,繼續向下,碰到Promise.then異步任務,繼續扔隊列裏面,執行console.log('script end');再去執行當前宏任務裏面的微任務,即Promise.then回調函數,最後執行第二個宏任務定時器.
執行結果: script start script end promise1 promise2 setTimeout
const promise = new Promise((resolve,reject) => { console.log(1); resolve(); console.log(2); }); promise.then(()=>{ console.log(3); }); console.log(4);
Promise 構造函數是同步執行的,promise.then 中的函數是異步執行的。因此
執行結果: 1 2 4 3
var funcs = []; for(var i=0;i<10;i++) { funcs.push(function() { console.log(i); }); } funcs.forEach(function(func) { func(); });
基礎題,匿名函數中的 i 值只有在函數調用執行的時候纔會去尋找對應變量的,for循環結束後執行func()時,此時i變量已經變爲10(最後有個i++),因此循環打印了十次10,想依次打印0-9的話可使用當即執行函數解決或者使用ES6的塊級做用域let聲明變量i.
js中number類型的數字都是採用64位的雙精度浮點數進行存儲的,其中1個符號位(0正1負),11個指數位,52個尾數位。0.1用二進制表示以下:0.000110011001100110011001100110011001100110011001100110011...
如上能夠看出0.1二進制表示時尾數是超過52位的, 因此52位以後的會被捨去,這就有了浮點數存儲的精度丟失問題。
setTimeout(()=>{ console.log('b') new Promise((resolve,reject)=>{ console.log('c'); resolve() }).then(res => { console.log('f') }) },0); new Promise((resolve,reject) => { console.log('d') resolve() }).then(res => { console.log('a') setTimeout(()=>{ console.log('e') },0) })
原理同第一題,答案爲:dabcfe
let test1 = () => { console.log(this); }; function test2() { console.log(this); }; class t { test() { console.log(this); } } let test3 = t.prototype.test; test1.call(null); test2.call(null); test3.call(null);
先給出正確答案:
/// window ; window ; null (非嚴格模式), /// window ; null ; null (嚴格模式)
當call或apply的第一個參數爲null || undefined時 this指向window ||global
call方法的參數,應該是一個對象。若是參數爲空、null和undefined,則默認傳入全局對象
類和模塊的內部,默認就是嚴格模式,因此不須要使用use strict指定運行模式。只要你的代碼寫在類或模塊之中,就只有嚴格模式可用。考慮到將來全部的代碼,其實都是運行在模塊之中,因此 ES6 實際上把整個語言升級到了嚴格模式。
順便解釋一下call的用法,apply相似,參數不一樣而已:
call方法 語法:call(thisobj,[argq,arg2]) 定義:調用一個對象的一個方法,以另外一個對象替換當前對象 說明: call方法能夠用來代替一個對象調用一個方法,call方法能夠將一個函數的對象上下文從初始化改成新的對象,也就是括號裏面的本來的對象改成call()前面的對象、即用thisobj代替call前面的東西,最終用thisobj這個對象去執行call前面的方法。 若是沒有提供 thisObj 參數,那麼 Global 對象被用做 thisObj。
其實call纔是函數調用最原始的方式,如今咱們使用的直接myFunc(args)調用函數的方式其實就是call調用的語法糖
let iArray = []; function getRandom(istart, iend){ var iChoice =iend - istart + 1; return Math.floor(Math.random() * iChoice + istart); } /*Math.random()就是獲取 0-1 之間的隨機數(永遠獲取不到 1)*/ for(let i=0; i<10; i++){ let result= getRandom(10,100); iArray.push(result); } iArray.sort(function(a,b){ return a>b; }); console.log(iArray);
let foo=1; function bar(){ foo=10; return; functionfoo(){} } bar(); console.log(foo); //1
爲何是1而不是10先分析一下每步流程: 第一步:varfoo=1;全局變量foo被初始化賦值成1。 第二步:執行bar();方法。 第三步:bar()方法裏,函數聲明functionfoo(){}優先處理,這裏JavaScript解析語法時(在運行以前)函數優先於一切。因此foo被初始化賦值爲function(){}; 第四步:執行foo=10;這裏製造了一個假象,認爲沒有用var聲明指向的是外層foo=1;。其實不是。而是先在自身函數體裏找有沒有foo聲明,找到以前聲明的functionfoo(){};賦值成10,只是局部變量的值改寫。 第五步:輸出foo,這時找的是全局變量varfoo=1;輸出1。
<style> .box { line-height: 24px; background-color: lightblue; } .box span { line-height: 48px; border: 1px solid; } </style> <div class="box"> <span>content...</span> </div>
考察的是inline box模型,它的工做就是包裹每行文字,一個沒有設置height屬性的div的高度就是由一個一個line boxes的高度堆積而成的,撐開div高度的是line-height不是文字內容.MDN 文檔中對line-height的描述以下:
line-height CSS 屬性用於設置多行元素的空間量, 好比文本。對於塊級元素, 它指定元素行盒(line boxes)的最小高度。 對於非替代的inline元素, 它用於計算行盒(line box)的高度。
適用元素 all elements. It also applies to ::first-letter and ::first-line.
如上面最終顯示 .box 容器 height = 48px; 1. 將<span>標籤裏的內容 改成<span>content ... <br> content ... </span> 後, .box 的height = 96px(48px*2)。 2. 將<span>標籤裏的內容 改成content ... <br><span> content ... </span> 後, .box 的height = 48 + 24 = 72px。
半像素邊框固然不是簡單地把1px改成0.5px,瀏覽器中最小的像素單位爲1像素,是不能識別0.5個像素,
1.設置目標元素做爲定位參照 box{position:relative} 2.給目標元素添加一個僞元素before或者after,並設置絕對定位 .box:before{content:""; position:absolute;} 3.給僞元素添加1px邊框 border:1px solid #000; 4.設置僞元素的寬高爲目標元素的2倍 width:200%; height:200%; 5.縮小0.5倍(縮放到原來大小) transform-origin: 0 0; transform:scale(0.5,0.5); 6.把border 邊框在線框內繪製 box-sizing:border-box;
簡單地說,對象是引用數據類型,那你每次導入這個組件的時候,其實引用的是同一個內存地址,componentA改變了引用這塊地址的數據後,componentB中的這塊地址對應的數據也會被改變。
那是由於在js中,函數的{}纔有獨立的做用域,對象的{},if(){}是不構成做用域的.
函數裏面,每調用一次函數就會建立一個新的函數做用域,他們之間是互相獨立的,這樣的話,無論你同時引入同一個組件多少次,他們之間的組件屬性都是獨立的,互不干擾。
vue的響應式核心是Object.defineProperty實現的.
Object.defineProperty(obj, key, { set:function(){}, get:function(){} })
被Object.defineProperty綁定過的數據會被監聽到,改變這個對象的時候會觸發get和set事件,這也是vue的model層和view層通訊的基礎,其實vue中的Observer就是基於Object.defineProperty來實現的。
Observer是數據的觀察者,與model層直接通訊,當數據更改時,它會通知dep(專門管理數據監聽依賴的東西),dep會收集到它所須要的依賴,當get的時候,收集訂閱者(這裏的訂閱者實際上是觀察者模式下的訂閱者,簡單地說,就是它須要知道具體get什麼訂閱者,什麼是觀察者模式和發佈訂閱者設計模式,具體網上不少相關資料解釋),把他添加到依賴,好比,watch和computed都依賴一個data進行監聽或者計算,那麼dep會將這兩個不一樣的依賴收集。當set的時候會發布更新,通知watcher更新view層。一個屬性可能有多個依賴,每一個響應式數據都有一個Dep來管理它的依賴。
每個依賴又是依靠一箇中介的角色來通知變化從而更新視圖的,所以watcher能通知變化去執行各自的代碼,固然它也能區分本身所屬的依賴,好比本身是屬於data仍是watch仍是computed.
放兩張網上的圖能夠更明瞭的說明他們之間的關係,也能夠看看大佬們的文章,講的更仔細,想學會這種設計模式仍是要擼源碼,應付面試已經夠了。
原圖連接
v-model本質上就是一個語法糖,實現原理其實就是上面說過的數據綁定加上底層的input事件監聽,經過v-bind綁定一個數據傳給子組件,子組件裏面的model默認用value屬性接受,而後子組件監聽數據發生變化,emit觸發父組件的input事件,經過觸發事件來進行傳值,實現了父子組件數據的雙向綁定。
定義了一種一對多的依賴關係,即當一個對象的狀態發生改變的時候,全部依賴他的對象都會獲得通知。
觀察者模式是由具體目標(發佈者/被觀察者)調度的,而發佈/訂閱模式是由獨立的調度中心進行調度,因此觀察者模式的訂閱者與發佈者之間是存在依賴的,而發佈/訂閱模式則不會(至關於一箇中介的角色,一個全局的Event,發佈者不須要知道具體要通知誰,訂閱者也不須要知道具體是誰通知的);能夠說發佈訂閱模式是觀察者模式進一步解耦,在實際中被大量運用的一種模式。
單元測試:按空間切割,對每一個組件進行測試
好比,我要測試日期輸入框,那麼我編寫的測試用例應該包括如下部分:
E2E測試:按時間切割,對每一個流程進行測試
好比,我要測試搜索功能,那麼我編寫的測試用例應該模擬如下步驟:
vue init webpack test
1.v-on綁定多個方法:<p v-on="{click:dbClick,mousemove:MouseClick}"></p>
2.一個事件綁定多個函數:<p @click="one(),two()">點擊</p>
.lazy:
v-modeil不用多說,輸入框改變,這個數據就會改變,lazy這個修飾符會在光標離開input框纔會更新數據:
<input type="text" v-model.lazy="value">
.trim:
輸入框過濾首尾的空格:
<input type="text" v-model.trim="value">
.number:
先輸入數字就會限制輸入只能是數字,先字符串就至關於沒有加number,注意,不是輸入框不能輸入字符串,是這個數據是數字:
<input type="text" v-model.number="value">
.stop:
阻止事件冒泡,至關於調用了event.stopPropagation()方法。這個應該不須要解釋:
<button @click.stop="test">test</button>
.prevent:
阻止默認行爲,至關於調用了event.preventDefault()方法,好比表單的提交、a標籤的跳轉就是默認事件:
<a @click.prevent="test">test</a>
.self:
只有元素自己觸發時才觸發方法,就是隻有點擊元素自己纔會觸發。好比一個div裏面有個按鈕,div和按鈕都有事件,咱們點擊按鈕,div綁定的方法也會觸發,若是div的click加上self,只有點擊到div的時候纔會觸發,變相的算是阻止冒泡:
<div @click.self="test"></div>
.once:
只能用一次,不管點擊幾回,執行一次以後都不會再執行:
<div @click.once="test"></div>
.capture:
事件的完整機制是捕獲-目標-冒泡,事件觸發是目標往外冒泡,好比:
<div @click="test(1)"> <button @click="test(2)">test</button></div> 順序是2 1,capture的做用就是讓這個順序相反: <div @click.capture="test(1)"> <button @click="test(2)">test</button></div>
先1 後2。
.passive:
其實我不怎麼理解,官網解釋說能夠提高移動端的性能,查了查,大概解釋就是每次滾動都會有一個默認事件觸發,加了這個就是告訴瀏覽器,不須要查詢,不須要觸發這個默認事件preventDefault:
<!-- 滾動事件的默認行爲 (即滾動行爲) 將會當即觸發 --> <!-- 而不會等待 `onScroll` 完成 --> <!-- 這其中包含 `event.preventDefault()` 的狀況 --> <div v-on:scroll.passive="onScroll">...</div>
.native:
組件綁定當前組件的事件是不會觸發的,須要用native才能觸發:
<My-component @click="shout(3)"></My-component>
鼠標.left、.reight、.middle:
就是鼠標點擊的時候就觸發:
<button @click.right="test">test</button>
.keyCode:
監聽按鍵的指令,具體能夠查看vue的鍵碼對應表:
<input type="text" @keyup.enter="test(1)"> <button @click.enter="test(1)">test</button>
注意,只有你點擊過一次或者聚焦到這個輸入框才能使用鍵盤觸發。
.exact:
系統修飾鍵,只有按着這個鍵而後用鼠標點擊纔會觸發,官網解釋:
<!-- 即便 Alt 或 Shift 被一同按下時也會觸發 --> <button @click.ctrl="onClick">A</button> <!-- 有且只有 Ctrl 被按下的時候才觸發 --> <button @click.ctrl.exact="onCtrlClick">A</button> <!-- 沒有任何系統修飾符被按下的時候才觸發 --> <button @click.exact="onClick">A</button>
可是我試了一下沒有用。
.sync
對prop進行雙向綁定,我的暫時用不習慣:
//父組件 <fa-comp :fatest.sync="test"></fa-comp> //子組件 this.$emit('update:fatest,sontest);
......
持續更新~