1.箭頭函數(shù)使用需要注意的地方
this歌懒、new具壮、arguments
- this對象的指向是可變的茶袒,但在箭頭函數(shù)中是固定的梯刚,指向定義時所在的對象,而非調(diào)用時所在的對象
- 不可以做構(gòu)造函數(shù)薪寓,也就是不能使用new亡资,否則拋出一個錯誤
- 不可以使用arguments澜共,因為它在函數(shù)體內(nèi)不存在,可以用rest代替
2.將arguments轉(zhuǎn)換為數(shù)組
var arr = Array.prototype.slice.apply(arguments)锥腻;
可以理解為arguments.slice()(當然arguments里面沒有slice方法)
var arr = [...arguments];
3.rest參數(shù)
用于獲取函數(shù)的多余參數(shù),它是一個數(shù)組
add(...values){ } //values獲取的是add的全部參數(shù)
add(arr, ...values){ }//values獲取的是剩余的參數(shù)
注意:rest參數(shù)只能是最后一個參數(shù)嗦董,否則報錯;
rest參數(shù)可替代arguments
//arguments變量的寫法
const sortNum = () => Array.prototype.slice.call(arguments).sort();
//rest參數(shù)的寫法
const sortNum = (...numbers) => numbers.sort();
4.擴展運算符...
作用:將數(shù)組轉(zhuǎn)換為一個參數(shù)序列
//ES5的寫法
var arr1 = [0,1,2];
var arr2 = [3,4,5];
Array.prototype.push.apply(arr1,arr2);
console.log(arr1);
打印: [0, 1, 2, 3, 4, 5]
//使用ES6
var arr1 = [0,1,2];
var arr2 = [3,4,5];
arr1.push(...arr2);
//ES5的寫法
var arr1 = [0,1,2];
var arr2 = [3,4,5];
console.log(arr1.concat(arr2));
打邮莺凇: [0, 1, 2, 3, 4, 5]
var arr1 = [0,1,2];
var arr2 = [3,4,5];
[arr1,...arr2];
應(yīng)用:
- 解構(gòu)賦值
const [first, ...rest] = [1,2,3,4,5];
first //1
rest //[2,3,4,5]
*將字符串轉(zhuǎn)換成真正的數(shù)組
[...'hello']
//['h','e','l','l','o']
注意:擴展運算符也只能放在最后一位京革,否則報錯
5.當new Foo()時發(fā)生了什么
- 創(chuàng)建了一個新對象
- 將this指向這個新對象
- 執(zhí)行構(gòu)造函數(shù)里面的代碼
- 返回新對象(this)
6.你做過哪些性能優(yōu)化 - 網(wǎng)頁內(nèi)容
1.減少http請求(通過 合并圖片,合并CSS和JS文件)
2.減少DNS的查詢(DNS預(yù)解析)
3.使用CDN - CSS
1.將樣式表置頂
2.少用@import - js
1.使用外部js和css(因為可以被緩存)
2.減少dom操作
7..前端路由的原理
什么是路由幸斥?
簡單的說匹摇,路由是根據(jù)不同的 url 地址展示不同的內(nèi)容或頁面
原理:在 HTML5 的 history API 出現(xiàn)之前,前端的路由都是通過 hash 來實現(xiàn)的甲葬,hash 能兼容低版本的瀏覽器廊勃。 - HTML5 History
兩個新增的API: history.pushState 和 history.replaceState,兩個 API 都會操作瀏覽器的歷史記錄经窖,而不會引起頁面的刷新坡垫。 - Hash
就是url 中看到 # ,我們需要一個根據(jù)監(jiān)聽哈希變化觸發(fā)的事件( hashchange) 事件。我們用 window.location 處理哈希的改變時不會重新渲染頁面画侣,而是當作新頁面加到歷史記錄中冰悠,這樣我們跳轉(zhuǎn)頁面就可以在 hashchange 事件中注冊 ajax 從而改變頁面內(nèi)容。
8.call,apply和bind的區(qū)別
它們在功能上是沒有區(qū)別的配乱,都是改變this的指向屿脐,它們的區(qū)別主要是在于方法的實現(xiàn)形式和參數(shù)傳遞上的不同
①:函數(shù).call(對象,arg1,arg2....)
②:函數(shù).apply(對象,[arg1,arg2,...])
③:var ss=函數(shù).bind(對象,arg1,arg2,....)
我們通過代碼來更加明顯的區(qū)別一下:
function show(sex){
console.log("普通函數(shù)"+sex);
}
var person={
name:"aa",
age:14
};
show.call(person,"男");
show.apply(person,["女"]);
//對于bind來說宪卿,用法更加的靈活
var ss=show.bind(person,"不明");
ss();
通過觀察上面的代碼的诵,很明顯的就可以得出它們?nèi)叩膮^(qū)別,僅僅是函數(shù)傳遞的不同以及bind方法可以更加的方便的使用
9.閉包的應(yīng)用
閉包+函數(shù)重寫
function foo() {
var context=1;
console.log(context);
context=2;
foo = function() {
console.log(context);
}
}
foo();
第一次打印1佑钾,之后都打印2
// 判斷element是否匹配選擇器selector
function matchSelector(element, selector) {
var match =
document.documentElement.webkitMatchesSelector ||
document.documentElement.mozMatchesSelector ||
document.documentElement.msMatchesSelector ||
// 兼容IE8及以下瀏覽器
function(selector, element) {
// 這是一個好方法西疤,可惜IE8連indexOf都不支持
// return Array.prototype.indexOf.call(document.querySelectorAll(selector), this) !== -1;
if (element.tagName === selector.toUpperCase()) return true;
var elements = document.querySelectorAll(selector),
length = elements.length;
while (length--) {
if (elements[length] === this) return true;
}
return false;
};
// 重寫函數(shù)自身,使用閉包keep住match函數(shù)休溶,不用每次都判斷兼容
matchSelector = function(element, selector) {
return match.call(element, selector);
};
return matchSelector(element, selector);
}
10.在地址欄里輸入一個URL,到這個頁面呈現(xiàn)出來代赁,中間會發(fā)生什么?
輸入url后兽掰,首先需要找到這個url域名的服務(wù)器ip,為了尋找這個ip芭碍,瀏覽器首先會尋找緩存,查看緩存中是否有記錄孽尽,緩存的查找記錄為:瀏覽器緩存-》系統(tǒng)緩存-》路由器緩存窖壕,緩存中沒有則查找系統(tǒng)的hosts文件中是否有記錄,如果沒有則查詢DNS服務(wù)器,得到服務(wù)器的ip地址后瞻讽,瀏覽器根據(jù)這個ip以及相應(yīng)的端口號鸳吸,構(gòu)造一個http請求,這個請求報文會包括這次請求的信息速勇,主要是請求方法晌砾,請求說明和請求附帶的數(shù)據(jù),并將這個http請求封裝在一個tcp包中烦磁,這個tcp包會依次經(jīng)過傳輸層养匈,網(wǎng)絡(luò)層,數(shù)據(jù)鏈路層都伪,物理層到達服務(wù)器乖寒,服務(wù)器解析這個請求來作出響應(yīng),返回相應(yīng)的html給瀏覽器院溺,因為html是一個樹形結(jié)構(gòu),瀏覽器根據(jù)這個html來構(gòu)建DOM樹磅轻,在dom樹的構(gòu)建過程中如果遇到JS腳本和外部JS連接珍逸,則會停止構(gòu)建DOM樹來執(zhí)行和下載相應(yīng)的代碼,這會造成阻塞聋溜,這就是為什么推薦JS代碼應(yīng)該放在html代碼的后面谆膳,之后根據(jù)外部央視,內(nèi)部央視撮躁,內(nèi)聯(lián)樣式構(gòu)建一個CSS對象模型樹CSSOM樹漱病,構(gòu)建完成后和DOM樹合并為渲染樹,這里主要做的是排除非視覺節(jié)點把曼,比如script杨帽,meta標簽和排除display為none的節(jié)點,之后進行布局嗤军,布局主要是確定各個元素的位置和尺寸注盈,之后是渲染頁面,因為html文件中會含有圖片叙赚,視頻老客,音頻等資源,在解析DOM的過程中震叮,遇到這些都會進行并行下載胧砰,瀏覽器對每個域的并行下載數(shù)量有一定的限制,一般是4-6個苇瓣,當然在這些所有的請求中我們還需要關(guān)注的就是緩存尉间,緩存一般通過Cache-Control、Last-Modify、Expires等首部字段控制乌妒。 Cache-Control和Expires的區(qū)別在于Cache-Control使用相對時間汹想,Expires使用的是基于服務(wù)器 端的絕對時間,因為存在時差問題撤蚊,一般采用Cache-Control古掏,在請求這些有設(shè)置了緩存的數(shù)據(jù)時,會先 查看是否過期侦啸,如果沒有過期則直接使用本地緩存槽唾,過期則請求并在服務(wù)器校驗文件是否修改,如果上一次 響應(yīng)設(shè)置了ETag值會在這次請求的時候作為If-None-Match的值交給服務(wù)器校驗光涂,如果一致庞萍,繼續(xù)校驗 Last-Modified,沒有設(shè)置ETag則直接驗證Last-Modified忘闻,再決定是否返回304
(1)域名---ip钝计,先從緩存找,沒有去系統(tǒng)的hosts文件齐佳,沒有再去DNS服務(wù)器查詢
(2)發(fā)起http請求私恬,求封裝在一個tcp包中,這個tcp包會依次經(jīng)過傳輸層炼吴,網(wǎng)絡(luò)層本鸣,數(shù)據(jù)鏈路層,物理層到達服務(wù)器
(3)服務(wù)器解析后硅蹦,返回html樹
(4)在dom樹的構(gòu)建過程中如果遇到JS腳本和外部JS連接荣德,則會停止構(gòu)建DOM樹來執(zhí)行和下載相應(yīng)的代碼,這會造成阻塞童芹,這就是為什么推薦JS代碼應(yīng)該放在html代碼的后面
(5)之后根據(jù)外部央視涮瞻,內(nèi)部央視,內(nèi)聯(lián)樣式構(gòu)建一個CSS對象模型樹CSSOM樹假褪,
(6)構(gòu)建完成后和DOM樹合并為渲染樹饲宛,這里主要做的是排除非視覺節(jié)點,比如script嗜价,meta標簽和排除display為none的節(jié)點艇抠,
(7)布局,布局主要是確定各個元素的位置和尺寸久锥,
(8)渲染
/**函數(shù)節(jié)流**/
function throttle(method,duration){
var begin=new Date();
return function(){
var context=this, args=arguments, current=new Date();
if(current-begin>=duration){
method.apply(context,args);
begin=current;
}
}
}
function resizehandler(){
console.log(++n);
}
window.onresize=throttle(resizehandler,500);
/**函數(shù)的去抖動**/
function debounce(method,delay){
var timer=null;
return function(){
var context=this, args=arguments;
clearTimeout(timer);
timer=setTimeout(function(){
method.apply(context,args);
},delay);
}
}
function resizehandler(){
console.log(++n);
}
window.onresize=debounce(resizehandler,500);