前端知識點

關於排序

  • js中sort函數的底層實現機制?

js中sort內置多種排序算法,是根據要排序數的亂序程度來決定使用哪種排序方法。V8 引擎 sort 函數只給出了兩種排序 InsertionSort 和 QuickSort,長度小於20的使用InsertionSort(插入排序),大於20的數組則使用 QuickSort(快速排序)javascript

快速排序css

function quickSort(arr){
        if(arr.length<=1){ //若是數組中只有一位數,返回數組
            return arr;
        }
        var mNumIndex = Math.floor(arr.length/2); //取基準值的下標
        var mNum = arr.splice(mNumIndex,1)[0];  //取基準值
        var left = [];  //左邊數組
        var right = []; //右邊數組
        for(var i=0;i<arr.length;i++){
            if(arr[i]<mNum){  //若是數組小於基準值,放在左邊數組
                left.push(arr[i]);
            }else{            ///不然
                right.push(arr[i]);
            }
        }        
        return quickSort(left).concat([mNum],quickSort(right));
        //返回左邊數組+基準值+右邊數組
    }

插入排序html

function insertSort(arr) {
  let length = arr.length;
  for(let i = 1; i < length; i++) {
    let temp = arr[i];
    for(let j = i; j > 0; j--) {
      if(arr[j] >= arr[j-1]) {
        break;      // 當前考察的數大於前一個數,證實有序,退出循環
      }
      arr[j] = arr[j-1]; // 將前一個數複製到後一個數上
    }
    arr[j] = temp;  // 找到考察的數應處於的位置
  }
  return arr;
}

選擇排序(實現思路跟冒泡排序差很少, 能夠說是冒泡排序的衍生版本)vue

function selectionSort(arr) {
      var len = arr.length
      var minIndex, temp
      for (i = 0; i < len - 1; i++) {
        minIndex = i
        for (j = i + 1; j < len; j++) {
          if (arr[j] < arr[minIndex]) {
            minIndex = j
          }
        }
        temp = arr[i]
        arr[i] = arr[minIndex]
        arr[minIndex] = temp
      }
      return arr
    }

數組去重

ES6java

function unique(arr) {
      return Array.from(new Set(arr))
    }
    new Set自己是一個構造函數,用來生成Set數據結構,類數組,成員的值都是惟一的,
    沒有重複的值。
    Array.from()將一個類數組對象或者可遍歷對象轉換成一個真正的數組。

ES5node

function unique(arr) {
      var newArr = []
      for (var i = 0; i < arr.length; i++) {
        if (newArr.indexOf(arr[i]) === -1) {
          newArr.push(arr[i])
        }
      }
     return newArr
   }
    var result = [];    
    var obj = {};    
    for(var i =0; i<arr.length; i++){
       if(!obj[arr[i].key]){
          result.push(arr[i]);
          obj[arr[i].key] = true;
       }
    }

如何統計網頁裏出現多少種html標籤

ES5webpack

var doms = document.getElementsByTagName('*')
    var obj = {}
    var ret = []
    for (let i = 0; i < doms.length; i++) {
      var name = doms[i].nodeName
      if(!obj[name]){
        ret.push(name)
        obj[name] = true
      }
    }
    console.log(ret.length)

ES6ios

let names = [...document.getElementsByTagName('*')].map(v=>v.nodeName)
   console.log(new Set(names).size)

獲取dom下的全部節點

function getDom(dom) {
      var list = []
      var domChildren = dom.childNodes
      for (var i = 0; i < domChildren.length; i++) {
        // nodeType === 1 是元素節點,2是屬性節點。
        if (domChildren[i].nodeType === 1) {
          list.push(domChildren[i])
          var retArr = getDom(domChildren[i])
          list = list.concat(retArr)
        }
      }
      return list
    }
    getDom(document.querySelector('body'))

實現bind方法:web

Function.prototype.bind= function(obj){
    var _self = this, args = arguments;
    return function() {
        _self.apply(obj, Array.prototype.slice.call(args, 1));
    }
}

防抖功能函數,接受傳參

定義:屢次觸發事件後,事件處理函數只執行一次,而且是在觸發操做結束時執行。

原理:對處理函數進行延時操做,若設定的延時到來以前,再次觸發事件,則清除上一次的延時操做定時器,從新定時。
    function debounce(fn) {
      // 四、建立一個標記用來存放定時器的返回值
      let timeout = null;
      return function() {
        // 五、每次當用戶點擊/輸入的時候,把前一個定時器清除
        clearTimeout(timeout);
        // 六、而後建立一個新的 setTimeout,
        // 這樣就能保證點擊按鈕後的 interval 間隔內
        // 若是用戶還點擊了的話,就不會執行 fn 函數
        var args = arguments;
        timeout = setTimeout(() => {
          fn.apply(this, args);
        }, 1000);
      };
    }
    sayDebounce(){
     console.log("防抖成功!");
    }
    btn.addEventListener("click", debounce(sayDebounce));

函數節流

定義:觸發函數事件後,短期間隔內沒法連續調用,只有上一次函數執行後,過了規定的時間間隔,才能進行下一次的函數調用。算法

原理:對處理函數進行延時操做,若設定的延時到來以前,再次觸發事件,則清除上一次的延時操做定時器,從新定時。

JavaScript中經常使用的設計模式

詳細連接: https://juejin.im/post/5afe64...

  • 1.單例模式
特色:一個類只能構造出惟一實例 
案例:建立菜單對象或者彈出框
const singleton = function(name) {
  this.name = name
  this.instance = null
}

singleton.prototype.getName = function() {
  console.log(this.name)
}

singleton.getInstance = function(name) {
  if (!this.instance) { // 關鍵語句
    this.instance = new singleton(name)
  }
  return this.instance
}

// test
const a = singleton.getInstance('a') // 經過 getInstance 來獲取實例
const b = singleton.getInstance('b')
console.log(a === b)
  • 2.工廠模式

建立一個對象經常須要複雜的過程,因此不適合在一個複雜的對象中。建立對象可能會致使大量的重複代碼,也可能提供不了足夠級別的抽象。工廠方法模式經過定義一個單獨的建立對象的方法來解決這些問題,由子類實現這個方法來建立具體類型的對象。

function Animal(opts){
    var obj = new Object();
    obj.name = opts.name;
    obj.color = opts.color;
    obj.getInfo = function(){
        return '名稱:'+obj.name +', 顏色:'+ obj.color;
    }
    return obj;
}
var cat = Animal({name: '波斯貓', color: '白色'});
cat.getInfo();
  • 3. 訂閱/發佈者模式

發佈訂閱模式,基於一個主題/事件通道,但願接收通知的對象(稱爲subscriber)經過自定義事件訂閱主題,被激活事件的對象(稱爲publisher)經過發佈主題事件的方式被通知。

就和用戶訂閱微信公衆號道理同樣,一個公衆號能夠被多個用戶同時訂閱,當公衆號有新增內容時候,只要發佈就行了,用戶就能接收到最新的內容

訂閱/發佈者模式和觀察者模式的區別:

在觀察者模式中,觀察者須要直接訂閱目標事件。在目標發出內容改變的事件後,直接接收事件並做出響應。發佈訂閱模式相比觀察者模式多了個事件通道,訂閱者和發佈者不是直接關聯的。
一、Observer模式要求觀察者必須訂閱內容改變的事件,定義了一個一對多的依賴關係;
二、Publish/Subscribe模式使用了一個主題/事件通道,這個通道介於訂閱着與發佈者之間;
三、觀察者模式裏面觀察者「被迫」執行內容改變事件(subject內容事件);發佈/訂閱模式中,訂閱着能夠自定義事件處理程序;
四、觀察者模式兩個對象之間有很強的依賴關係;發佈/訂閱模式兩個對象之間的耦合讀底

function Public(){
        //存放訂閱者信息
        this.subscribers = [];
        // 添加訂閱者
        this.addSubscriber = function(subscriber) {
          //保證一個訂閱者只能訂閱一次
          let flag = this.subscribers.some(function(item){
            return item == subscriber;
          })
          if(!flag){
            this.subscribers.push(subscriber);
          }
          return this;
        }
        // 發佈消息
        this.publish = function(data) {
          let arr = arguments; 
          this.subscribers.forEach(function(fn){
            fn(...arr)
          })
          return this;
        }
      }
      let publisher = new Public() //初始化
      let fanfan = function(data){
        console.log(`訂閱者吳亦凡收到訂閱信息:${[...arguments]}`)
      }
      let luhan = function(data){
        console.log(`訂閱者鹿晗收到訂閱信息:${[...arguments]}`)
      }
      publisher.addSubscriber(fanfan).addSubscriber(luhan); // 添加訂閱者fanfan
      publisher.publish('NBA頭條快訊', '蔡徐坤簽約掘金');
  1. 3. 觀察者模式

一個或多個觀察者對目標的狀態感興趣,經過將本身依附在目標對象上以便註冊所感興趣的內容。目標狀態發生改變而且觀察者可能對這些改變感興趣,會發送一個通知消息,調用每一個觀察者的更新方法。當觀察者再也不對目標狀態感興趣時,他們能夠簡單將本身從中分離。

首先是目標的構造函數,他有個數組,用於添加觀察者。還有個廣播方法,遍歷觀察者數組後調用他們的update方法:
class Subject{
  constructor(){
    this.subs = [];
  }
  addSub(sub){
    this.subs.push(sub);
  }
  notify(){
    this.subs.forEach(sub=> {
      sub.update();
    });
  }
}
那麼觀察者就得有個update方法:
class Observer{
  update(){
    console.log('update');
  }
}
let subject = new Subject();
let ob = new Observer();
//目標添加觀察者了
subject.addSub(ob);
//目標發佈消息調用觀察者的更新方法了
subject.notify();   //update

4. 策略模式
特徵:根據不一樣參數能夠命中不一樣的策略;
案例:動畫庫裏的算法函數
5. 代理模式
特徵:代理對象和本體對象具備一致的接口;
案例:圖片預加載
5. 迭代器模式
特徵:能獲取聚合對象的順序和元素;
案例:each([1, 2, 3], cb);
5. 命令模式
特徵:不一樣對象間約定好相應的接口;
案例:按鈕和命令的分離;
6. 組合模式
特徵:組合模式在對象間造成一致對待的樹形結構;
案例: 掃描文件夾;
7. 組合模式
特徵:組合模式在對象間造成一致對待的樹形結構;
案例: 掃描文件夾;
6. 組合模式
特徵:組合模式在對象間造成一致對

  1. 列表項目

待的樹形結構;
案例: 掃描文件夾;

判斷數組

Object.prototype.toString.call(arr) === "[object Array]" ;
Array.isArray(arr);
arr.constructor === Array;

This的指向

  1. 全局範圍:指向winodow(嚴格模式下不存在全局變量,指向undedfiend);
  2. 普通函數調用:指向window
  3. 對象方法調用:指向最後調用它的對象
  4. 構造函數調用:指向new出來的對象
  5. 顯示設置this: call apply 方法顯示將this指向第一個參數指明的對象
  6. 箭頭函數沒有prototype(原型),因此箭頭函數自己沒有this, 箭頭函數的this指向在定義的時候繼承自外層第一個普通函數的this,跟使用位置沒有關係。被繼承的普通函數的this指向改變,箭頭函數的this指向會跟着改變,不能直接修改箭頭函數的this指向(call、aaply、bind)會默認忽略第一個參數,可是能夠正常傳參。

什麼是原型鏈?

建立一個函數就會爲其建立一個prototype屬性,指向這個函數的原型對象,原型對象會自動得到constructor屬性,指向prototype屬性所在函數。

Function.prototype.a = "a";   
Object.prototype.b = "b";   
function Person(){}   
console.log(Person);    //function Person()   
let p = new Person();   
console.log(p);         //Person {} 對象   
console.log(p.a);       //undefined   
console.log(p.b);       //b
p.__proto__ === Person.prototype;Person.prototype.constructor === Person;

640?wx_fmt=jpeg&wxfrom=5&wx_lazy=1&wx_co=1

new操做符具體幹了什麼呢?

  1. 建立一個空對象,而且 this 變量引用該對象,同時還繼承了該函數的原型。
  2. 屬性和方法被加入到 this 引用的對象中。
  3. 新建立的對象由 this 所引用,而且最後隱式的返回 this 。

頁面加載過程

  1. 瀏覽器根據 DNS 服務器獲得域名的 IP 地址
  2. 向這個 IP 的機器發送 HTTP 請求
  3. 服務器收到、處理並返回 HTTP 請求
  4. 瀏覽器獲得返回內容

Vue實現數據雙向綁定的原理:Object.defineProperty()

vue實現數據雙向綁定主要是:採用數據劫持結合發佈者-訂閱者模式的方式,經過Object.defineProperty()來劫持各個屬性的setter,getter,在數據變更時發佈消息給訂閱者,觸發相應監聽回調。當把一個普通 Javascript 對象傳給 Vue 實例來做爲它的 data 選項時,Vue 將遍歷它的屬性,用 Object.defineProperty 將它們轉爲 getter/setter。用戶看不到 getter/setter,可是在內部它們讓 Vue 追蹤依賴,在屬性被訪問和修改時通知變化。

vue的數據雙向綁定 將MVVM做爲數據綁定的入口,整合Observer,Compile和Watcher三者,經過Observer來監聽本身的model的數據變化,經過Compile來解析編譯模板指令(vue中是用來解析 {{}}),最終利用watcher搭起observer和Compile之間的通訊橋樑,達到數據變化 —>視圖更新;視圖交互變化(input)—>數據model變動雙向綁定效果。

<body>
    <div id="app">
    <input type="text" id="txt">
    <p id="show"></p>
</div>
</body>
<script type="text/javascript">
    var obj = {}
    Object.defineProperty(obj, 'txt', {
        get: function () {
            return obj
        },
        set: function (newValue) {
            document.getElementById('txt').value = newValue
            document.getElementById('show').innerHTML = newValue
        }
    })
    document.addEventListener('keyup', function (e) {
        obj.txt = e.target.value
    })
</script>

對vue的keep-alive 的瞭解

keep-alive是 Vue 內置的一個組件,可使被包含的組件保留狀態,或避免從新渲染。
在vue 2.1.0 版本以後,keep-alive新加入了兩個屬性: include(包含的組件緩存) 與 exclude(排除的組件不緩存,優先級大於include) 。

Vue.js的template編譯的理解?

答:簡而言之,就是先轉化成AST樹,再獲得的render函數返回VNode(Vue的虛擬DOM節點)

詳情步驟:

首先,經過compile編譯器把template編譯成AST語法樹(abstract syntax tree 即 源代碼的抽象語法結構的樹狀表現形式),compile是createCompiler的返回值,createCompiler是用以建立編譯器的。另外compile還負責合併option。

而後,AST會通過generate(將AST語法樹轉化成render funtion字符串的過程)獲得render函數,render的返回值是VNode,VNode是Vue的虛擬DOM節點,裏面有(標籤名、子節點、文本等等)

Vue.nextTick

在下次 DOM 更新循環結束以後執行延遲迴調。在修改數據以後當即使用這個方法,獲取更新後的 DOM。
原理:事件循環機制(Event Loop)
如下事件屬於宏任務:

setInterval()
setTimeout()
如下事件屬於微任務

new Promise()
new MutaionObserver()

  1. MutationObserver監聽DOM更新完畢的。
  2. vue用異步隊列的方式來控制DOM更新和nextTick回調前後執行
  3. microtask(微任務)由於其高優先級特性,能確保隊列中的微任務在一次事件循環前被執行完畢
  4. 由於兼容性問題,vue不得不作了microtask向macrotask(Promise)的降級方案

VUE的watch與computed的區別

  • 觸發條件不一樣

1.computed計算屬性會依賴於使用它的data屬性,只要是依賴的data屬性值有變更,則自定義從新調用計算屬性執行一次。
2.watch則是在監控的data屬性值發生變更時,其會自動調用watch回調函數。

  • 應用場景不一樣

1.執行異步操做,開銷較大的操做,避免堵塞主線程,使用watch。
2.簡單且串行返回的,使用computed

請解釋閉包

《JavaScript權威指南》中的概念:有權訪問另外一個做用域中變量的函數
閉包特性:可實現函數外訪問函數內變量,外層變量能夠不被垃圾回收機制回收。
缺點:

  1. 在閉包中使用this對象可能會致使一些問題,由於匿名函數的執行具備全局性,所以其this對象一般指window.
  2. 因爲閉包會使得函數中的變量都被保存在內存中,內存消耗很大,因此不能濫用閉包,不然會形成網頁的性能問題,在IE中可能致使內存泄露。解決方法是,在退出函數以前,將不使用的局部變量所有刪除.
function outer() {
  var a = 2;
  function inner() {
    console.log(a);
  }
  return inner;
}
var neal = outer();
neal();//2

JS數據類型

基礎類型:Undefined, Null, Boolean, Number, String, Symbol(ES6新增,表示獨一無二的值))一共6種
引用類型:Object

JS中的基礎數據類型,這些值都有固定的大小,每每都保存在棧內存中(閉包除外),由系統自動分配存儲空間。咱們能夠直接操做保存在棧內存空間的值,所以基礎數據類型都是按值訪問 數據在棧內存中的存儲與使用方式相似於數據結構中的堆棧數據結構,遵循後進先出的原則。

JS的引用數據類型,好比數組Array,它們值的大小是不固定的。引用數據類型的值是保存在堆內存中的對象。JS不容許直接訪問堆內存中的位置,所以咱們不能直接操做對象的堆內存空間。在操做對象時,其實是在操做對象的引用而不是實際的對象。所以,引用類型的值都是按引用訪問的。這裏的引用,咱們能夠粗淺地理解爲保存在棧內存中的一個地址,該地址與堆內存的實際值相關聯。
clipboard.png

數據結構:

數據結構就是關係,沒錯,就是數據元素相互之間存在的一種或多種特定關係的集合。
邏輯結構:是指數據對象中數據元素之間的相互關係,也是咱們從此最須要關注和討論的問題。
物理結構:是指數據的邏輯結構在計算機中的存儲形式。

常見的數據結構:
數組,隊列(queue),堆(heap),棧(stack),鏈表(linked list ),樹(tree),圖(graph)和散列表(hash)

參照:https://www.cnblogs.com/slly/...

  • 棧:

一種遵循後進先出(LIFO)原則的有序集合。新添加的或待刪除的元素都保存在棧的同一端,稱做棧頂,另外一端就叫棧底。在棧裏,新元素都接近棧頂,舊元素都接近棧底。

  • 隊列(queue):

是隻容許在一端進行插入操做,而在另外一端進行刪除操做的線性表。與棧相反,隊列是一種先進先出(First In First Out, FIFO)的線性表。與棧相同的是,隊列也是一種重要的線性結構,實現一個隊列一樣須要順序表或鏈表做爲基礎。

  • 鏈表:

鏈表存儲有序的元素集合,但不一樣於數組,鏈表中的元素在內存中並非連續放置的。每一個元素由一個存儲元素本事的節點和一個指向下一個元素的引用組成。相對於傳統的數組,鏈表的一個好處在於,添加或者刪除元素的時候不須要移動其餘元素。 使用鏈表結構能夠克服數組須要預先知道數據大小的缺點(C語言的數組須要預先定義長度),鏈表結構能夠充分利用計算機內存空間,實現靈活的內存動態管理。 數組和鏈表的一個不一樣在於數組能夠直接訪問任何位置的元素,而想要訪問鏈表中的一個元素,須要從起點開始迭代列表。

click在ios上有300ms延遲,緣由及如何解決?

  1. 粗暴型,禁用縮放
<meta name="viewport" content="width=device-width, user-scalable=no">
  1. 利用FastClick,其原理是:
檢測到touchend事件後,馬上出發模擬click事件,而且把瀏覽器300毫秒以後真正出發的事件給阻斷掉

css盒模型

1.IE盒子模型(怪異盒子)box-sizing :border-box;
寬度=margin+width
2.W3C標準盒模型box-sizing : content-box;

寬度=margin+border+padding+width

選擇器權重

!important > 行內樣式>ID選擇器 > 類選擇器 > 標籤 > 通配符* > 繼承 > 瀏覽器默認屬性

有幾種方法清楚浮動

1. 父元素 overflow: hidden;
2.浮動元素後面的元素: clear: both;
3.僞元素選擇器:.clear::after{ content:’’;display:block; clear:both;};
4.父元素設置高度;
5.父級元素:display: table;

如何作水平垂直居中?

方案一:已知寬高,設置position: absolute;,而後left和top都設置爲50%,再根據margin的負值來調正
方案二:相似方案一,最後一步用transform:translate(-50%,-50%);
方案三:絕對定位,top、bottom、left、right都設置爲0,設置好寬高,而後margin: auto;
方案四:display:table-cell; + vertical-align:middle;
方案五:使用flex彈性盒模型

<div class=「box」>
    <div class=「item」></div>
</div>
box{
    display:flex;
    justifly-content:center;
    Align-item:center;
}
Box{
    Position:relative;
}
Item{
 Position:absolute;
 Top:50%;
 Transform:translateY(-50%);
}

選擇器權重

!important > 行內樣式>ID選擇器 > 類選擇器 > 標籤 > 通配符* > 繼承 > 瀏覽器默認屬性

webpack的一些原理和機制

webpack:把全部依賴打包成一個 bundle.js 文件,經過代碼分割成單元片斷並按需加載。

  1. 解析webpack配置參數,合併從shell傳入和webpack.config.js文件裏配置的參數,生產最後的配置結果。
  2. 註冊全部配置的插件,好讓插件監聽webpack構建生命週期的事件節點,以作出對應的反應。
  3. 從配置的entry入口文件開始解析文件構建AST語法樹,找出每一個文件所依賴的文件,遞歸下去。
  4. 在解析文件遞歸的過程當中根據文件類型和loader配置找出合適的loader用來對文件進行轉換。
  5. 遞歸完後獲得每一個文件的最終結果,根據entry配置生成代碼塊chunk。
  6. 輸出全部chunk到文件系統。

ES6模塊與CommonJS模塊的差別

  1. CommonJs 模塊輸出的是一個值的拷貝,ES6模塊輸出的是一個值的引用
  2. CommonJS 模塊是運行時加載,ES6模塊是編譯時輸出接口
  3. ES6輸入的模塊變量,只是一個符號連接,因此這個變量是隻讀的,對它進行從新賦值就會報錯

模塊加載AMD,CMD,CommonJS Modules/2.0 規範

AMD 是 RequireJS 在推廣過程當中對模塊定義的規範化產出(不過 RequireJS 從 2.0 開始,也改爲能夠延遲執行(根據寫法不一樣,處理方式不一樣))。
CMD 是 SeaJS 在推廣過程當中對模塊定義的規範化產出。

  1. 這些規範的目的都是爲了 JavaScript 的模塊化開發,特別是在瀏覽器端的
  2. 對於依賴的模塊,AMD 是提早執行,CMD 是延遲執行
  3. CMD 推崇依賴就近,AMD 推崇依賴前置

繼承方式

相關文案

  1. 原型鏈繼承
  2. 借用構造函數 (類式繼承)
  3. 組合式繼承(原型+構造函數繼承)
  4. 原型式繼承
  5. 寄生式繼承
  6. 寄生組合式繼承
父子類
function Animal(name) {
    this.name = name || "Mike";//實例屬性
    this.love = function () {
      console.log(this.name + "愛吃骨頭")//實例方法
    }
    this.other = [];//實例引用屬性
  }
  Animal.prototype.sleep = function (place) {
    console.log(this.name + "在" + place + "睡覺")
  }
  • 原型鏈繼承
function Dog() {}
  Dog.prototype = new Animal();
  Dog.prototype.name = "Jack";
  var dog1 = new Dog("twoHa");
  var dog2 = new Dog("keJi");
  console.log(dog1.name);//Jack
  console.log(dog2.name);//Jack
  dog1.love();//Jack愛吃骨頭
  dog2.love();//Jack愛吃骨頭
  dog1.sleep("牀上");//Jack在牀上睡覺
  dog2.sleep("客廳");//Jack在客廳睡覺

優勢:
 1. 實例是子類的實例,也是父類的實例
 2. 父類新增原型方法/原型屬性,子類都能訪問到
 3. 簡單,易於實現

缺點:

 1. 要想爲子類新增屬性和方法,必需要在new Animal()這樣的語句以後執行,不能放到構造器中
 2. 沒法實現多繼承
 3. 來自原型對象的引用屬性是全部實例共享的,改變實例會污染父類
 4. 建立子類實例時,沒法向父類構造函數傳參

XSS和CSRF

XSS跨站腳本攻擊:
不須要你作任何的登陸認證,它會經過合法的操做(好比在url中輸入、在評論框中輸入),向你的頁面注入腳本(多是js、hmtl代碼塊等)。

  • 編碼:當惡意代碼值被做爲某一標籤的內容顯示:在不須要html輸入的地方對html 標籤及一些特殊字符( 」 < > & 等等)作過濾,將其轉化爲不被瀏覽器解釋執行的字符。
  • 在標籤的 href、src 等屬性中,包含 javascript: (僞協議)等可執行代碼。
  • 過濾:移除用戶輸入的和事件相關的屬性。如onerror能夠自動觸發攻擊,還有onclick等。移除用戶輸入的Style節點、Script節點、Iframe節點。(尤爲是Script節點,它但是支持跨域的呀,必定要移除);
  • httpOnly: 在 cookie 中設置 HttpOnly 屬性後,js腳本將沒法讀取到 cookie 信息。
  • jsonp引起的xss攻擊
  • 就是前面說到的,Content-Type 不要亂用,嚴格按照標準協議來作。目前的框架默認確定會檢測一下內容類型,若是不是很必要,不要手動設置。由於有可能多轉發幾回 Content-Type 就被改了。
  • callback 作長度限制,這個比較 low。

檢測 callback 裏面的字符。通常 callback 裏面都是字母和數字,別的符號都不能有。

  • callback 作一個編碼,若是用 Go 語言作的話,以下。對全部 callback 都處理。callback = template.JSEscapeString(callback)
  • CSRF攻擊:跨站請求僞造。

要完成一次CSRF攻擊,受害者必須知足兩個必要的條件:

  • 登陸受信任網站A,並在本地生成Cookie。(若是用戶沒有登陸網站A,那麼網站B在誘導的時候,請求網站A的api接口時,會提示你登陸)
  • 在不登出A的狀況下,訪問危險網站B(實際上是利用了網站A的漏洞)。

舒適提示一下,cookie保證了用戶能夠處於登陸狀態,但網站B其實拿不到 cookie。
預防

  • Token 驗證:(用的最多)

(1)服務器發送給客戶端一個token;
(2)客戶端提交的表單中帶着這個token。
(3)若是這個 token 不合法,那麼服務器拒絕這個請求。

  • 隱藏令牌:

把 token 隱藏在 http 的 head頭中。
方法二和方法一有點像,本質上沒有太大區別,只是使用方式上有區別。

  • Referer 驗證:Referer 指的是頁面請求來源。意思是,只接受本站的請求,服務器才作響應;若是不是,就攔截。

XSS 與 CSRF異同

  • CSRF:須要用戶先登陸網站A,獲取 cookie。
  • XSS:不須要登陸。
  • CSRF:是利用網站A自己的漏洞,去請求網站A的api。
  • XSS:是向網站 A 注入 JS代碼,而後執行 JS 裏的代碼,篡改網站A的內容。

HTTP

HTTP是用於傳輸如HTML文件,圖片文件,查詢結果的應用層協議。它被設計於用於服務端和客戶端之間的通訊。

傳統輪詢(Traditional Polling)

當前Web應用中較常見的一種持續通訊方式,一般採起 setInterval 或者 setTimeout 實現。例如若是咱們想要定時獲取並刷新頁面上的數據,能夠結合Ajax寫出以下實現:

setInterval(function() {
    $.get("/path/to/server", function(data, status) {
        console.log(data);
    });
}, 10000);
缺陷:
程序在每次請求時都會新建一個HTTP請求,然而並非每次都能返回所需的新數據。
當同時發起的請求達到必定數目時,會對服務器形成較大負擔。
  • 長輪詢(long poll)

客戶端發送一個request後,服務器拿到這個鏈接,若是有消息,才返回response給客戶端。沒有消息,就一直不返回response。以後客戶端再次發送request, 重複上次的動做。

http協議的特色是服務器不能主動聯繫客戶端,只能由客戶端發起。它的被動性預示了在完成雙向通訊時須要不停的鏈接或鏈接一直打開,這就須要服務器快速的處理速度或高併發的能力,是很是消耗資源的。

websocket 和http區別

 相同點:

  1. 都是應用層的協議
  2. 都是基於tcp,而且都是可靠的協議

不一樣點:

  1. websocket是持久鏈接的協議,而http是非持久鏈接的協議.
  2. websocket是雙向通訊協議,模擬socket協議,能夠雙向發送消息,而http是單向的.
  3. websocket的服務端能夠主動向客服端發送信息,而http的服務端只有在客戶端發起請求時才能發送數據,沒法主動向客戶端發送信息.

迴流與重繪

  1. 當render tree(渲染樹)中的一部分(或所有)由於元素的規模尺寸,佈局,隱藏等改變而須要從新構建。這就稱爲迴流(reflow)。每一個頁面至少須要一次迴流,就是在頁面第一次加載的時候。在迴流的時候,瀏覽器會使渲染樹中受到影響的部分失效,並從新構造這部分渲染樹,完成迴流後,瀏覽器會從新繪製受影響的部分到屏幕中,該過程成爲重繪。
  2. 當render tree中的一些元素須要更新屬性,而這些屬性只是影響元素的外觀,風格,而不會影響佈局的,好比background-color。則就叫稱爲重繪。

注意:迴流必將引發重繪,而重繪不必定會引發迴流。

    • 當頁面佈局和幾何屬性改變時就須要迴流。下述狀況會發生瀏覽器迴流:
    1. 添加或者刪除可見的DOM元素;
    2. 元素位置改變;
    3. 元素尺寸改變——邊距、填充、邊框、寬度和高度
    4. 內容改變——好比文本改變或者圖片大小改變而引發的計算值寬度和高度改變;
    5. 頁面渲染初始化;
    6. 瀏覽器窗口尺寸改變——resize事件發生時;

    請詳細說下你對vue生命週期的理解?

    總共分爲8個階段建立前/後,載入前/後,更新前/後,銷燬前/後
    beforeCreate 建立前執行(vue實例的掛載元素$el和數據對象data都爲undefined,還未初始化)

    1. created 完成建立 (完成了data數據初始化,el還未初始化)
    2. beforeMount 載入前(vue實例的$el和data都初始化了,但仍是掛載以前爲虛擬的dom節點,data.message還未替換。)
    3. mounted 載入後html已經渲染(vue實例掛載完成,data.message成功渲染。)
    4. beforeUpdate 更新前狀態(view層的數據變化前,不是data中的數據改變前)
    5. updated 更新狀態後
    6. beforeDestroy 銷燬前
    7. destroyed 銷燬後 (在執行destroy方法後,對data的改變不會再觸發周期函數,說明此時vue實例已經解除了事件監聽以及和dom的綁定,可是dom結構依然存在)

    說一下每個階段能夠作的事情

    1. beforeCreate:能夠在這裏加一個loading事件,在加載實例時觸發。
    2. created:初始化完成時的事件寫這裏,若是這裏結束了loading事件,異步請求也在這裏調用。
    3. mounted:掛在元素,獲取到DOM節點
    4. updated:對數據進行處理的函數寫這裏。
    5. beforeDestroy:能夠寫一個確認中止事件的確認框。
    相關文章
    相關標籤/搜索