2017.10.1

1. 實現(xiàn)不同窗體間互相通信

(1) window.postMessage()支持跨文檔消息傳輸(Cross Document Messaging),并且可跨域傳輸信息。
兼容性:IE>=8 支持

消息監(jiān)聽:onmessage,可接受任意發(fā)送過來的消息,應對消息來源(e.origin)進行安全驗證

window.addEventListener('message', fn, false);

消息發(fā)送:postMessage,獲取到要傳送消息的窗體對象,向其發(fā)送消息。

targetWindow.postMessage(message, targetOrigin); 

(2) 監(jiān)聽 localStoragestorage事件,當localStorage的鍵值改變時,就會觸發(fā)此事件。

window.addEventListener("storage", fn, false);
window.attachEvent("onstorage", fn);

2. CORS

CORS(跨域資源共享)需要瀏覽器和服務器同時支持,除IE<10以外,其他瀏覽器都已支持,而且服務器實現(xiàn)了CORS接口,就可以跨源通信了。通過在服務器端設置 HTTP header 字段,服務器可以聲明哪些網(wǎng)站有權限訪問哪些資源。

瀏覽器將CORS請求分兩類,簡單請求非簡單請求。

(1) 簡單請求:(不會觸發(fā)CORS預檢請求)
條件:1. 請求方法是HEAD GETPOST; 2. HTTP header是對CORS安全的首部字段。
瀏覽器和服務器之間使用 CORS 首部字段來處理跨域權限。瀏覽器在請求頭信息中增加一個Origin字段,用來說明本次請求來自哪個源,服務器根據(jù)這個字段值來決定是否同意這次請求。
如果Origin指定的源不在許可范圍,服務器會返回一個正常的 HTTP 回應,這個回應的頭信息不包含Access-Control-Allow-Origin字段,瀏覽器會拋出一個錯誤,這個錯誤會被 XMLHttpRequestonerror 回調函數(shù)捕獲。這個錯誤不能通過狀態(tài)碼識別,因為服務器返回的是一個正常的回應,狀態(tài)碼可能為200。
如果Origin指定的源在許可范圍內,服務器返回的響應會包含幾個頭信息字段:Access-Control-Allow-Origin (Access-Control-Allow-Credentials、Access-Control-Expose-Headers、Content-Type 可選)

(2)非簡單請求:(會進行預檢請求)
條件:對服務器有特殊要求的請求,請求方法是PUTDELETE,或者Content-Type字段類型是application/json。
非簡單請求會在正式通信前,增加一次HTTP預檢請求。
瀏覽器會先詢問服務器,當前域名是否在服務器許可名單中,以及可以使用哪些HTTP請求方法和頭信息字段,當?shù)玫椒掌骺隙ɑ貞?,會返?code>Access-Control-Allow-Origin字段,表示可以請求數(shù)據(jù)。如果服務器返回否定回應,會觸發(fā)一個錯誤,被XMLHttpRequestonerror 回調函數(shù)捕獲。

3. flex-box

彈性盒子(flexible box)是CSS3的一種新的布局模式,尤其是在屏幕寬度自適應時,彈性布局使得父元素中子元素的排列、對齊、空間分配變得更便捷靈活。對于可伸縮的父元素,子元素隨其擴大或縮小,并能夠合適地填滿父元素空間。彈性布局包括多個CSS3屬性,有設置在父元素上的,有設置在子元素上的。

父元素上的屬性:
display:flex; 讓父元素變成Flex容器。
flex-direction:子元素在Flex容器中放置的方向 (row|row-reverse|column|column-reverse)
flex-wrap:默認子元素都顯示在一行(nowrap),改變此屬性(wrap/wrap-reverse),可以讓子元素多行顯示。
justify-content:在主軸上對齊子元素,在父元素有多余的空間時才會進行空間分配 (flex-start|flex-end|center|space-between|space-around)
align-items:在側軸上對齊子元素(flex-start|flex-end|center|baseline|stretch)
align-content:當多行的Flex容器的側軸還有多余空間時,可用來調節(jié)多行子元素在容器內的對齊方式(flex-start|flex-end|center|space-between|space-around|stretch)

子元素上的屬性:
order:默認子元素是按文檔中的順序顯示排列的,在Flex容器中可通過order屬性改變子元素的顯示順序
flex-grow:可以定義子元素的擴大比例。所有的子元素值相同時,占據(jù)相同的空間。
flex-shrink:可以定義子元素的縮小比例。
flex-basis:子元素的分配Flex容器剩余空間之前的默認尺寸。0表示不考慮子元素周圍額外空間,auto表示額外空間根據(jù)flex-grow值做分配。
flexflex-grow、flex-shrinkflex-basis三個屬性的縮寫。默認值:0 1 auto。
align-self:單個子元素側軸的對齊方式。

4. 前端優(yōu)化

(1) 加載頁面和靜態(tài)資源方面:
靜態(tài)資源的合并壓縮;使用緩存;使用CDN;后端渲染,數(shù)據(jù)直接輸出到html模版

(2)頁面渲染和頁面操作方面:
減少DOM操作;懶加載;css放在html文檔的前面加載,js在后面加載;事件節(jié)流;盡早執(zhí)行操作(DOMContentLoaded: DOM渲染完即可操作,此時圖片視頻可能還沒加載完;window.onload:頁面全部資源加載完才會執(zhí)行,包括圖片視頻)

5. BFC

塊級格式化上下文(block formatting context),創(chuàng)建了新BFC的盒子是獨立布局的,是一個隔離的獨立容器盒子,里面子元素的樣式不會影響到外面的元素,盒子里的子元素的布局和定位和外部元素互不影響。

作用:
(1) 避免margin重疊。塊級標簽之間豎直方向的margin會重疊??梢杂?code>overflow:hidden;來解決。
(2) 清除浮動。子元素浮動,父元素的高度會塌陷,父元素高度不會被子元素撐開的問題。

觸發(fā)BFC的條件:
(1) 浮動元素:float的值不為none。
(2) position的值為absolutefixed。
(3) overflow為除了visible以外的值(autoscrollhidden)。
(4) display的值為inline-block、table-celltable-caption。

6. web安全-攻擊及防范

(1) XSS 跨站腳本攻擊(Cross Site Scripting)
攻擊者向web頁面插入惡意html標簽或者js代碼。比如一個看似安全的鏈接,用戶點擊后,攻擊者竊取用戶的cookie;或者攻擊者在網(wǎng)頁中加一個惡意表單,用戶提交表單的時候,把消息傳送到攻擊者的服務器,而不是原本的站點。
防范:對用戶輸入做字符過濾或者轉義;避免在cookie中泄露用戶隱私;最好使用POST提交表單。

(2) CSRF 跨站請求偽造(Cross-site request forgery)
要完成一次CSRF攻擊,關鍵點:登錄受信任的網(wǎng)站A,并在本地生成cookie;在不登出A的情況下,訪問危險網(wǎng)站B。
防范:通過驗證碼或者token檢測用戶;避免全站通用cookie,設置cookie的域;用戶操作最好都使用POST。

7. getElementsByClassName

獲取頁面元素的方法:
getElementById() 返回一個對象
getElementsByTagName() 返回集合
getElementsByClassName() 返回集合
querySelector() 返回一個對象
querySelectorAll() 返回集合

8. 前端路由實現(xiàn)的方式

(1)h5: window.history
兼容性:IE<=9 不支持

window.history.pushState(data, title, url); 
window.history.replaceState(data, title, url);

url: 絕對路徑/相對路徑, 同域。
這兩個API可操作瀏覽器的歷史棧,而不會引起頁面刷新。
區(qū)別:pushState會在歷史記錄中增加一條,replaceState會替換當前的歷史記錄。

(2)hash: 當頁面的 hash (window.location.hash) 發(fā)生變化時,會觸發(fā)hashchange事件。
兼容性:IE<=7 不支持

window.onhashchange = fn;  
window.addEventListener("hashchange", fn, false);

9. 一個DOM元素綁定既綁定了冒泡事件,又綁定了捕獲事件,執(zhí)行順序是?

綁定在同一個DOM元素上的事件,是按照事件聲明的順序執(zhí)行的,無論是捕獲還是冒泡;
這個DOM元素能夠“感知”到的綁定在其他元素上的事件(比如綁定在其父元素上的事件),會按照先捕獲事件,后冒泡事件的順序執(zhí)行。

var box = document.getElementById('box');    // 容器
var btn = document.getElementById('button'); // 容器內的按鈕
// btn
btn.addEventListener('click', function(){   //1
    console.log('bubble','btn');
}, false);
btn.addEventListener('click', function(){   //2
    console.log('capture','btn');
}, true);
// box
box.addEventListener('click', function(){   //3
    console.log('bubble','box');
}, false);
box.addEventListener('click', function(){   //4
    console.log('capture','box');
}, true);

//點擊按鈕,console.log:  
  "capture" "box"  //4
  "bubble" "btn"   //1
  "capture" "btn"  //2
  "bubble" "box"   //3

//調換1、2順序,打印結果順序也會調換
//調換3、4順序,打印結果不調換

10. HTTP及HTTP的緩存機制

11.apply、call、bind的區(qū)別

call、apply和bind都可以改變函數(shù)內部this的指向。第一個參數(shù)都是this要指向的對象。

call和apply都可以改變某個函數(shù)運行的上下文,函數(shù)內部的this指向call/apply的第一個參數(shù)。創(chuàng)建的時候會立即調用函數(shù)。
區(qū)別:函數(shù)的參數(shù)傳入call/apply時,call第二個及其以后的參數(shù)位置依次傳入函數(shù)的參數(shù)。apply的第二個參數(shù)是一個數(shù)組,是函數(shù)參數(shù)的數(shù)組。

bind會創(chuàng)建一個新的函數(shù)(綁定函數(shù)),創(chuàng)建的時候不會立即調用。當調用這個函數(shù)時,綁定函數(shù)會以創(chuàng)建時傳入bind()方法的第一個參數(shù)作為this,第二個及其以后的參數(shù)依次傳入原函數(shù)的參數(shù)。

call/apply:

// 獲取數(shù)組中的最大或最小值
var numbers = [1, 2, 3, 100, -100];

Math.max(...numbers);
Math.max.call(null, ...numbers);   // 100
Math.max.apply(null, numbers);   // 100
// 判斷是否是數(shù)組
function isArray(obj) {
    return Object.prototype.toString.call(obj) === '[object Array]';
}

bind:

var x = 1;
var module = {
    x: 2,
    getX: function(){
        return this.x;
    }
}
var fn = module.getX.bind(module);
fn();   // 2

12. 一個DOM元素注冊多個事件,怎樣做到只執(zhí)行第一個事件,后面事件不執(zhí)行?

(1)設置一個全局變量,同一個事件的所有回調函數(shù)都會判斷這個條件,條件滿足就執(zhí)行,執(zhí)行的時候就將這個條件置為false,這樣就能保證只有第一個回調函數(shù)會執(zhí)行。

var btn = document.getElementById('button');
var flag = true;

btn.addEventListener('click', function(){
    console.log(1);
    if(flag) console.log('1-inner');
    flag = false;
}, false);

btn.addEventListener('click', function(){
    console.log(2);
    if(flag) console.log('2-inner');
}, false);

btn.addEventListener('click', function(){
    console.log(3);
    if(flag) console.log('3-inner');
}, false);

// console.log:
  1
  1-inner
  2
  3

我覺得,這不是個好方法。因為對于注冊在元素上的多個同名事件,其實每個事件都執(zhí)行了。在執(zhí)行到回調函數(shù)內部再進行條件判斷,并不算真正意義上的只執(zhí)行了第一個事件吧。

(2)執(zhí)行某個回調函數(shù)時取消事件監(jiān)聽

// 同一元素注冊多個事件,同一個回調函數(shù)
var btn = document.getElementById('button');
var handler = function(){
    console.log('1')
    btn.removeEventListener('click', handler, false);
}
btn.addEventListener('click', handler, false);
btn.addEventListener('click', handler, false);
btn.addEventListener('click', handler, false);

// console.log:
   1

這種方法,需要保證多個綁定事件的回調函數(shù)是同一個。如果多個事件綁定多個回調函數(shù),則無效。

(3)利用Promise.race()

Promise.race()方法簡介:

Promise.race函數(shù)返回一個Promise,這個Promise的完成方式,取決于傳遞進去的多個Promise哪個先完成,可以是成功resolve,也可以是失敗reject。

var p1 = new Promise(function(resolve, reject){
    setTimeout(resolve, 1000, 'one');
});
var p2 = new Promise(function(resolve, reject){
    setTimeout(resolve, 2000, 'two');
});
var p3 = new Promise(function(resolve, reject){
    setTimeout(reject, 500, 'three');  // 最快執(zhí)行
});
var p4 = new Promise(function(resolve, reject){
    setTimeout(reject, 1000, 'four');
})

Promise.race([p1, p2, p3, p4]).then(function(value){
    console.log(value);
}, function(reason){
    console.log(reason);
});

// console.log:
  'three'

一個DOM元素注冊多個事件,只執(zhí)行第一個事件。利用Promise.race()實現(xiàn):

var btn = document.getElementById('btn');

var handler = function(){
    console.log('done');
};
var handler2 = function(){
    console.log('done2');
};
var handler3 = function(){
    console.log('done3');
};

var p1 = new Promise(function(resolve, reject){
    console.log(1);
    btn.addEventListener('click', handler, false);
    resolve();
});
var p2 = new Promise(function(resolve, reject){
    console.log(2);
    btn.addEventListener('click', handler2, false);
    resolve();
});
var p3 = new Promise(function(resolve, reject){
    console.log(3);
    btn.addEventListener('click', handler3, false);
    resolve();
});

Promise.race([p1, p2, p3]).then(function(){
    console.log('race');
    btn.removeEventListener('click', handler2, false);
    btn.removeEventListener('click', handler3, false);
})

// 點擊按鈕,依次打?。?  1
  2
  3
  race
  done
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,506評論 19 139
  • Web前端技術由html、css和 javascript 三大部分構成,是一個龐大而復雜的技術體系,其復雜程度不低...
    WEB攻程獅閱讀 1,927評論 2 116
  • 一:在制作一個Web應用或Web站點的過程中,你是如何考慮他的UI、安全性、高性能、SEO、可維護性以及技術因素的...
    Arno_z閱讀 1,354評論 0 1
  • RESTful API的設計,是以請求方式GET、POST、PUT等為動作,URL為動作請求的資源名詞的標準來設計...
    云勺閱讀 4,539評論 0 5
  • Web 前端知識體系精簡 2017-06-20 前端大全 作者:一像素 www.cnblogs.com/onepi...
    灰猩猩閱讀 934評論 0 4

友情鏈接更多精彩內容