3.JavaScript

原文鏈接:https://github.com/helloyoucan/knowledge

JavaScript相關(guān)

1、聲明相關(guān)
  • var變量提升,function函數(shù)提升,function >var(優(yōu)先級(jí))
  • 塊級(jí)作用域:with、try/catchlet、const
  • let ,不可重復(fù)聲明,暫時(shí)性死區(qū)
  • const,不可重復(fù)聲明、修改,暫時(shí)性死區(qū)
2、JS引擎
任務(wù)隊(duì)列
  • JS分為同步任務(wù)、異步任務(wù)。
  • 同步任務(wù)在主線程上執(zhí)行,形成一個(gè)Call Stack(執(zhí)行棧)。
  • 主線程之外,事件觸發(fā)線程管理著一個(gè)Task Queue(任務(wù)隊(duì)列),當(dāng)異步任務(wù)完成時(shí),會(huì)指定對(duì)應(yīng)的事件(回調(diào))進(jìn)入Task Queue。
  • 一旦Call Stack(執(zhí)行棧)中所有同步任務(wù)執(zhí)行完畢(此時(shí)JS引擎空閑),系統(tǒng)就會(huì)讀取Task Queue,將Task Queue中可運(yùn)行的事件添加到Call Stack(執(zhí)行棧)中,開始執(zhí)行。
  • 事件循環(huán)是通過任務(wù)隊(duì)列機(jī)制來(lái)進(jìn)行協(xié)調(diào)的。
  • 一個(gè)Event Loop中,可以有一個(gè)或者多個(gè)任務(wù)隊(duì)列(task queue),一個(gè)任務(wù)隊(duì)列就是一系列有序任務(wù)(task)的集合
  • 每個(gè)任務(wù)都要一 個(gè)任務(wù)源(task source),源自同一個(gè)任務(wù)源的task必須放到同一個(gè)任務(wù)隊(duì)列,從不同源來(lái)的則被添加到不同隊(duì)列。
  • setTimeout/Promise等API便是任務(wù)源,而進(jìn)入任務(wù)隊(duì)列的是他們指定的具體執(zhí)行任務(wù)。

<img src="./images/task.png" style="width:500px"/>

宏任務(wù)
  • (macro)task(宏任務(wù)),可以理解為每次執(zhí)行棧執(zhí)行的代碼就行一個(gè)宏任務(wù)(包括每次從Task Queue中獲取一個(gè)事件(回調(diào))并放到執(zhí)行棧中執(zhí)行)。
  • macrotask中的事件(回調(diào))都是放在一個(gè)事件隊(duì)列中(Task Queue)的,而這個(gè)隊(duì)列由事件觸發(fā)線程維護(hù)。
  • 瀏覽器為了能夠使得JS內(nèi)部(macro)task與DOM任務(wù)能夠有序地執(zhí)行,會(huì)在一個(gè)task執(zhí)行結(jié)束后,在下一個(gè)task執(zhí)行開始前,對(duì)頁(yè)面進(jìn)行渲染(task->渲染->task->......)。
  • macrotask主要包含:script(整體代碼)、setTimeout/setInterval、I/O、UI交互事件、postMessage、MessageChannel(創(chuàng)建消息通道傳遞消息的api,可用在iframe上)、setImmediate(Node.js環(huán)境)
微任務(wù)
  • microtask(又稱為微任務(wù)),可以理解是當(dāng)前task執(zhí)行結(jié)束后立刻執(zhí)行的任務(wù)(在當(dāng)前macrotask后,渲染前,下一個(gè)macrotask前)。
  • 產(chǎn)生的microtask會(huì)添加到微任務(wù)隊(duì)列(Microtask Queues)中,該隊(duì)列由JS引擎線程維護(hù)。
  • 響應(yīng)速度比macrotask(例如setTimeout)會(huì)更快,因?yàn)闊o(wú)需等渲染。(某個(gè)macrotask執(zhí)行后,就會(huì)將在它執(zhí)行期間產(chǎn)生的所有microtask都執(zhí)行完畢(在渲染前))。
  • microtask主要包含:Promise.then(原生的,部分實(shí)行可能是task)、MutationObserver(監(jiān)聽DOM變化的api)、process.nextTick(Node.js環(huán)境)。

微任務(wù)和宏任務(wù)皆為異步任務(wù),主要區(qū)別在于他們的執(zhí)行順序,Event Loop的走向和取值。

運(yùn)行機(jī)制

在事件循環(huán)(Event Loop)中,每進(jìn)行一次循環(huán)操作成為tick,每一次tick的任務(wù)處理模型是比較復(fù)制的,但關(guān)鍵步驟如下:

  • 執(zhí)行Call Stack(執(zhí)行棧)一個(gè)宏任務(wù)(棧中沒有就從事件隊(duì)列(Task Queue)中獲取)
  • 執(zhí)行過程中如果遇到微任務(wù),就將它添加到微任務(wù)的任務(wù)隊(duì)列中
  • 宏任務(wù)執(zhí)行完畢后,立即執(zhí)行當(dāng)前微任務(wù)隊(duì)列中的所有微任務(wù)(依次執(zhí)行)
  • 當(dāng)前宏任務(wù)執(zhí)行完畢,開始檢查渲染,然后GUI線程接管渲染
  • 渲染完畢后,JS線程繼續(xù)接管,開始下一個(gè)宏任務(wù)(從事件隊(duì)列中獲?。?/li>

<img src="/images/執(zhí)行機(jī)制.jpg" style="width:300px;"/>

3、 閉包

有權(quán)訪問另外一個(gè)函數(shù)作用域中的變量的函數(shù)

用途
  • 設(shè)計(jì)私有方法和變量
  • 單例模式
  • 模塊化——使用閉包模塊化代碼,減少全局變量的使用
缺陷
  • 閉包會(huì)常駐在內(nèi)存中,不會(huì)被垃圾回收機(jī)制主動(dòng)回收,增大內(nèi)存使用量,使用不當(dāng)容易泄露
  • 閉包對(duì)腳本性能有負(fù)面效果,比如處理速度和內(nèi)存消耗
4、異步執(zhí)行
  • 動(dòng)態(tài)插入腳本
  • defer="defer"——IE支持,頁(yè)面解釋完成時(shí)執(zhí)行,按照加載順序執(zhí)行
  • async="async"——加載完成則執(zhí)行
5、數(shù)據(jù)類型
  • 基本類型

    Number、String、Boolean、Undefined、Null、Symbol

  • 引用類型

    Objcet、Array、Function

主要要點(diǎn):

  • typeof {} 或 null 或 [ ] === "object"
6、原型鏈

<img src="/images/原型鏈.png" style="width:500px;"/>

實(shí)例、構(gòu)造函數(shù)、原型對(duì)象

  • 實(shí)例 = new 構(gòu)造函數(shù)
  • 實(shí)例.__proto__ === 原型對(duì)象
  • 構(gòu)造函數(shù).prototype === 原型對(duì)象
  • 原型對(duì)象.constructor === 構(gòu)造函數(shù)
  • 原型對(duì)象.__proto__ === 原型鏈上一級(jí)的原型對(duì)象
instanceof
  • 判斷 實(shí)例.__proto__ === 原型鏈上任意的構(gòu)造函數(shù)(原型對(duì)象).prototype
  • 實(shí)例.__proto__.constructor === 實(shí)例的構(gòu)造函數(shù)
New運(yùn)算符

new做了什么?

  1. 創(chuàng)建了一個(gè)全新的對(duì)象。
  2. 這個(gè)對(duì)象會(huì)被執(zhí)行[[Prototype]](也就是__proto__)鏈接。
  3. 生成的新對(duì)象會(huì)綁定到函數(shù)調(diào)用的this。
  4. 通過new創(chuàng)建的每個(gè)對(duì)象將最終被[[Prototype]]鏈接到這個(gè)函數(shù)的prototype對(duì)象上。
  5. 如果函數(shù)沒有返回對(duì)象類型Object(包含Functoin, Array, Date, RegExg, Error),那么new表達(dá)式中的函數(shù)調(diào)用會(huì)自動(dòng)返回這個(gè)新的對(duì)象。
function Func(name){this.name = name};
var o1 = new Func('name1')
//模擬new
function new2(func,...param){
   /*
    //Object.create的作用
    function F(){}
    F.prototype = func.prototype
    var o =new F()
   */
    var o = Object.create(func.prototype)
    var ret = func.apply(o,param)
    return ret instanceof Object ? ret : o; //構(gòu)造函數(shù)return了內(nèi)容可以這樣
}
var o2 = new2(Func,'name2')
7、this
  • this是一個(gè)關(guān)鍵字
  • 代表函數(shù)運(yùn)行時(shí),自動(dòng)生成的一個(gè)內(nèi)部對(duì)象,只能在函數(shù)內(nèi)部使用
  • this是在執(zhí)行時(shí)確定是什么值,定以時(shí)無(wú)法確定
  • this指向的是,調(diào)用函數(shù)的那個(gè)對(duì)象
  • bind(this)、call(this,p1,p2,...)、apply(this,[p1,p2,....])
8、繼承
  1. 借助原型鏈實(shí)現(xiàn)繼承

    /*
    缺點(diǎn):
    1.父類中的屬性(也就是父類this上的屬性)是子類共用
    2.子類實(shí)例時(shí)無(wú)法向父類傳參(因?yàn)楦割愒缫褜?shí)例化)
    */
    function P(){}
    function C(){}
    C.prototype = new P()
    
  2. 構(gòu)造函數(shù)實(shí)現(xiàn)繼承

    /*
    缺點(diǎn):
    1.子類無(wú)法繼承父類的prototype
    2.若父類方法綁定在this上則每個(gè)子類都會(huì)copy一份,違背代碼復(fù)用
    */
    function P(){}
    P.prototype.say = function(){}//子類無(wú)法繼承
    function C(){ P.call(this,arguments) } //繼承父類屬性
    
  3. 組合式繼承

    /*
    缺點(diǎn)
    1.父類構(gòu)造函數(shù)調(diào)用兩次
    */
    function P(){}
    function C(){ P.call(this,arguments) } //P執(zhí)行了1次
    C.prototype = new P() // P執(zhí)行了2次
    
  4. 寄生組合繼承

    function P(){}
    function C(){ P.call(this,arguments) }
    //實(shí)現(xiàn)方式
    C.prototype = Object.create(P.prototype) //通過淺拷貝繼承父類方法,不需要調(diào)用一次父類構(gòu)造函數(shù)
    C.prototype.constructor = C // 上一行代碼對(duì)子類原型進(jìn)行了拷貝,因此子類的constructor屬性被重寫,所以需要這樣修復(fù)
    
  5. extends繼承

    class P(){}
    class C extends P(){
      constructor(){
        super() //獲得this對(duì)象
      }
    }
    
ES5的繼承 vs ES6的繼承

ES5

  • ES5的繼承是通過prototype或構(gòu)造函數(shù)機(jī)制來(lái)實(shí)現(xiàn)
  • ES5繼承的實(shí)質(zhì)是先創(chuàng)建子類實(shí)例,再將父類方法添加到this上。

ES6

  • ES6是先創(chuàng)建父類實(shí)例對(duì)象this(先調(diào)用super()方法),再用子類構(gòu)造函數(shù)修改this。
  • ES6通過class關(guān)鍵字定以類,里面有構(gòu)造方法,類之間通過extend關(guān)鍵字實(shí)現(xiàn)繼承。子類必須在constructor方法中調(diào)用super方法,否則新建實(shí)例失敗。因?yàn)樽宇悰]有自己的this對(duì)象,而是繼承父類的this對(duì)象,然后對(duì)齊加工。如果不調(diào)用super方法,子類得不到this對(duì)象。
9、Promise
  • Promise是一種用于解決異步問題的思路、方案或者對(duì)象方式。

  • 狀態(tài):pending、fulfilledrejected

  • 寫法:

    new Promise((resolve,rejected)=>{
      //success
      setTimeout(()=>{
          resolve('success')
      },2000)
      //fail
      rejected()
    })
    .then(()=>{})
    .catch(()=>{})
    .finally(()=>{})
    
  • 主要要點(diǎn):

    1. 一旦執(zhí)行resolve或rejected,后面的再執(zhí)行rejected或resolve則無(wú)效
    2. 執(zhí)行了resolve或rejected,Promise后面的代碼還會(huì)執(zhí)行下去
  • 靜態(tài)方法

    Promise.all([]) // 數(shù)組內(nèi) 所有 狀態(tài)都為fulfilled,則狀態(tài)變?yōu)閒ulfilled,數(shù)組內(nèi)其中一個(gè)狀態(tài)變?yōu)閞ejected,則狀態(tài)為rejected
    Promise.race([]) // 數(shù)組內(nèi) 其中一個(gè) 狀態(tài)都為fulfilled,則狀態(tài)變?yōu)閒ulfilled
    Promise.resolve() // 轉(zhuǎn)化為Promise對(duì)象,等價(jià)于new Promise(resolve => resolve())
    Promise.reject() // 轉(zhuǎn)化為Promise對(duì)象
    
10、Ajax
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(){
    if(xhr.readyState === 4){
        if(xhr.status===200||
           xhr.status===304||
           xhr.status===206){//媒體資源體積大,分步傳輸,狀態(tài)碼為206
            res = xhr.responseText
            if(typeof res==='string'){
                res = JSON.parse(res)
                console.log(res)
            }else{
                console.log(res)
            }
        }else{
            console.log(new Error(res))
        }
    }
}
xhr.open('GET','url',true)
xhr.send()
/*
xhr.open('POST','url',true)
xhr.setRequestHeader('content-type','application/json;charset=UTF-8')
xhr.send(JSON.stringify({}))
*/
  • 狀態(tài)碼
readState

0-(未初始化)還沒有調(diào)用send方法
1-(載入)已調(diào)用send()方法,正在發(fā)生請(qǐng)求
2-(載入完成)send方法執(zhí)行完成,已經(jīng)接收到前部響應(yīng)內(nèi)容
3-(交互)正在解析響應(yīng)內(nèi)容
4-(完成)響應(yīng)內(nèi)容解析完成,可以在客戶端調(diào)用了

status

2xx - 表示成功處理請(qǐng)求,如200
3xx - 需要重定向,瀏覽器直接跳轉(zhuǎn)
4xx - 客戶端請(qǐng)求錯(cuò)誤,如404
5xx - 服務(wù)器端錯(cuò)誤

11、跨域

同源策略:非同源(域名、協(xié)議、端口)的腳本不能訪問或者操作其它域的頁(yè)面對(duì)象。

由于同源策略,非同源之間需要通訊,所以就需要跨域訪問。

跨域,是指瀏覽器不能執(zhí)行其他網(wǎng)站的腳本。它是由瀏覽器的同源策略造成的,是瀏覽器對(duì)JavaScript實(shí)施的安全限制。

同源策略限制了一下行為:

  • Cookie、LocalStorage 和 IndexDB 無(wú)法讀取
  • DOM 和 JS 對(duì)象無(wú)法獲取
  • Ajax請(qǐng)求發(fā)送后response會(huì)被瀏覽器攔截
跨域通訊
  • JSONP(動(dòng)態(tài)插入js文件,文件中調(diào)用預(yù)先定義好的函數(shù)并傳入?yún)?shù))
  • Hash+ iframe
  • document.domain + iframe跨域 (適用于不同子域通訊)
  • postMessage(HTML5新增)
  • window.name + iframe(窗口載入所有頁(yè)面共享)
  • webScoket(協(xié)議不受同源策略限制)
  • 跨域資源共享CROS(服務(wù)端支持+絕對(duì)路徑訪問接口)
  • 代理服務(wù)器(nginx、node等)
12、優(yōu)化
頁(yè)面加載資源優(yōu)化
  • 靜態(tài)資源壓縮合并(減少http請(qǐng)求次數(shù)、減少文件體積)
  • 緩存資源
  • CDN
  • 按需加載資源(動(dòng)態(tài)加載腳本,圖片懶加載,數(shù)據(jù)下拉加載等)
  • 預(yù)加載(preload:強(qiáng)制瀏覽器不阻塞document.onload情況下請(qǐng)求資源;prefetch:告知瀏覽器將來(lái)可能需要,什么時(shí)候加載由瀏覽器決定)
  • 減少DOM的數(shù)量
  • 延遲加載腳本
  • 合理放置腳本位置(CSS放在前面加載,js文件放到頁(yè)面底部加載)
JavaScript執(zhí)行優(yōu)化
  • 緩存DOM查詢(減少DOM查詢,可對(duì)DOM查詢做緩存)
  • 合并DOM操作(減少DOM操作,可將多個(gè)操作合并為一個(gè))
  • 事件委托(使用事件委托的方式綁定事件)
  • 事件節(jié)流(一定時(shí)間內(nèi)任務(wù)執(zhí)行的次數(shù)。每次觸發(fā)事件時(shí)都取消之前的延時(shí)調(diào)用方法)
  • 事件防抖(在任務(wù)高頻率觸發(fā)的時(shí)候,只有觸發(fā)間隔超過制定間隔的任務(wù)才會(huì)執(zhí)行。每次觸發(fā)事件時(shí)都判斷當(dāng)前是否有等待執(zhí)行的延時(shí)函數(shù))
  • 慎用閉包(減少不必要的閉包的使用,及時(shí)釋放無(wú)用的內(nèi)存占用)
  • web worker執(zhí)行耗時(shí)代碼(耗時(shí)的代碼塊可移動(dòng)到web worker執(zhí)行)
雅虎軍規(guī)

網(wǎng)頁(yè)內(nèi)容

  • 減少http請(qǐng)求
  • 減少DNS查詢
  • 避免重定向
  • 緩存Ajax請(qǐng)求
  • 延遲加載
  • 預(yù)加載
  • 減少DOM元素?cái)?shù)量
  • 劃分內(nèi)容到不同域名(接口和靜態(tài)資源)
  • 減少iframe的使用
  • 避免404錯(cuò)誤

服務(wù)器

  • CDN
  • 靜態(tài)內(nèi)容添加Expires;動(dòng)態(tài)內(nèi)容設(shè)置Cache-Control報(bào)響應(yīng)頭
  • 啟用Gzip
  • 配置Etag
  • 盡早輸出(flush)緩沖
  • Ajax使用Get請(qǐng)求
  • 避免空的圖片src

cookie

  • 減少Cookie大小
  • 頁(yè)面靜態(tài)資源使用無(wú)Cookie域名

CSS

  • 樣式表放在<head>中
  • 避免css表達(dá)式
  • 使用<link>代替@import
  • 避免使用filters

JavaScript

  • 腳本置底
  • 外部js和css文件
  • 精簡(jiǎn)JavaScript和css
  • 去除重復(fù)腳本
  • 減少DOM訪問
  • 使用高效事件處理

圖片

  • 壓縮圖片
  • 優(yōu)化CSS Sprite
  • 不在HTML中縮放圖片
  • 使用小且可緩存的ico

ETags:是服務(wù)器和瀏覽器用來(lái)決定瀏覽器緩存中組件與源服務(wù)器中的組件是否匹配的一種機(jī)制(“實(shí)體”也就是組件:圖片,腳本,樣式表等等)。添加ETags可以提供一種實(shí)體驗(yàn)證機(jī)制,比最后修改日期更加靈活。一個(gè)ETag是一個(gè)字符串,作為一個(gè)組件某一具體版本的唯一標(biāo)識(shí)符。唯一的格式約束是字符串必須用引號(hào)括起來(lái),源服務(wù)器用相應(yīng)頭中的ETag來(lái)指定組件的ETag。

然后,如果瀏覽器必須驗(yàn)證一個(gè)組件,它用If-None-Match請(qǐng)求頭來(lái)把ETag傳回源服務(wù)器。如果ETags匹配成功,會(huì)返回一個(gè)304狀態(tài)碼,這樣就減少了12195個(gè)字節(jié)的響應(yīng)體。Etag 通過文件版本標(biāo)識(shí),方便服務(wù)器判斷請(qǐng)求的內(nèi)容是否有更新,如果沒有就響應(yīng) 304,避免重新下載。

13、事件綁定
種類
  • DOM0級(jí)(onclick=function(){})
  • DOM2級(jí)(addEventListener)
  • DOM3級(jí)(新增事件類型)
事件模型
  • 捕獲
  • 冒泡
事件流
  • 捕獲階段(從window對(duì)象自上而選向目標(biāo)節(jié)點(diǎn)傳播)
  • 目標(biāo)階段(目標(biāo)節(jié)點(diǎn)處理事件)
  • 冒泡階段(事件從目標(biāo)節(jié)點(diǎn)自下而上向window對(duì)象傳播)
事件綁定

addEventListener(event,function,useCapture)

event:事件類型

function:執(zhí)行函數(shù)

useCapture:可選;true:捕獲階段執(zhí)行;false(默認(rèn)):冒泡階段執(zhí)行

常用對(duì)象
event.preventDefault() //阻止默認(rèn)事件
event.stopPropagation() //阻止冒泡
event.stoplmmediatePropagation() //阻止其它事件的響應(yīng)(當(dāng)注冊(cè)了多個(gè)事件時(shí))
event.currentTarget //其監(jiān)聽器觸發(fā)事件的節(jié)點(diǎn)(綁定事件的元素),即當(dāng)前處理該事件的元素、文檔或窗口。
event.target //當(dāng)前被點(diǎn)擊的元素(舊版本的ie是sourceElement)
自定義事件
  • Event(IE不支持)

    var event = new Event(custome' //事件名稱
        {//可選
            bubbles:false,//是否冒泡
            cancelable:false,//能否被取消
            composed:false//是否會(huì)在影子DOM根節(jié)點(diǎn)之外觸發(fā)偵聽器
        })
    dom.addEventListener('custome',function(){})
    dom.dispatchEvent(event)
    
  • CustomEvent(IE不完全支持)

    var event = new CustomEvent('custome',
        {//可選
            bubbles:false,//是否冒泡
            cancelable:false,//能否被取消
            detail:{a:1,b:2} //當(dāng)事件初始化時(shí)傳遞的數(shù)據(jù)
        })
    dom.addEventListener('custome',function(e){ 
      console.log(e.detail.a,e.detail.b) 
    })
    dom.dispatchEvent(event)
    
  • document.createEvent(僅IE支持)

    var event = document.createEvent('HTMLEvents');
    event.hello='hello,I am event';
    event.initEvent('customEvent', true, true);//事件名稱;事件是否冒泡;事件是否可以被取消
    dom.addEventListener('customEvent', function(e){
        console.log(e.hello)
    }, false);
    dom.dispatchEvent(event)
    
14、本地存儲(chǔ)
  1. cookie

    • 4kb(不同瀏覽器存放大小不一樣,一般為4kb)

    • 不同瀏覽器存放位置(磁盤)不一樣

    • http請(qǐng)求會(huì)帶上

    • 字符串形式存在

    • 僅以域名區(qū)分(不同協(xié)議、端口、子域可共享)

    • 可設(shè)過期時(shí)間,默認(rèn)是會(huì)話結(jié)束則銷毀

    • document.cookie = "username=cfangxu; domain=qq.com; path=/" // 添加cookie,設(shè)置生效子域及路徑
      
  2. sessionStorage

    • 同源策略限制
    • 本質(zhì)是讀取字符串,存儲(chǔ)過多會(huì)消耗內(nèi)存,頁(yè)面變卡
    • 一般為5M
    • 非IE可本地打開,IE需要在服務(wù)器中打開
    • 通過跳轉(zhuǎn)打開新頁(yè)面會(huì)復(fù)制源頁(yè)面當(dāng)前會(huì)話的sessionStorage
    • 會(huì)話結(jié)束時(shí)刪除
  1. localStorage

    • 同源策略限制
    • 本質(zhì)是讀取字符串,存儲(chǔ)過多會(huì)消耗內(nèi)存,頁(yè)面變卡
    • 一般為5M
    • 非IE可本地打開,IE需要在服務(wù)器中打開
    • 修改時(shí)會(huì)觸發(fā)其它頁(yè)面storage事件
    • 同一域中共享
    • 持久化本地存儲(chǔ),需要主動(dòng)刪除,不會(huì)過期
15、安全
Cross-site requset forgery(CSRF,跨站請(qǐng)求偽造)
  • 原理:

    用戶已登錄A網(wǎng)站,同時(shí)用戶在瀏覽B網(wǎng)站,在B網(wǎng)站中誘導(dǎo)用戶點(diǎn)擊操作A網(wǎng)站的連接(例如一個(gè)關(guān)注某用戶的GET請(qǐng)求的連接)

  • 防御

    • Token認(rèn)證

    • Referer驗(yàn)證(頁(yè)面來(lái)源認(rèn)證)

    • 隱藏令牌(例如把令牌存放在頁(yè)面的<head>)

    • 驗(yàn)證碼

Cross Site Script(XSS,跨站腳本工具)
  • 原理:

    攻擊者在網(wǎng)站惡意注入的客戶端代碼,通過惡意腳本對(duì)網(wǎng)頁(yè)進(jìn)行篡改,在用戶瀏覽網(wǎng)頁(yè)時(shí),對(duì)用戶瀏覽器進(jìn)行控制或者獲取用戶隱私數(shù)據(jù)。

  • 防御

    • HttpOnly 防止劫取 Cookie(設(shè)置cookie是否能通過 js 去訪問)
    • 對(duì)用戶的任何輸入進(jìn)行檢查、過濾和轉(zhuǎn)義(XSS Filter)
    • 對(duì)服務(wù)端的輸出進(jìn)行檢查、過濾和轉(zhuǎn)義
16、函數(shù)式編程
  • 不可變性 (不能更改數(shù)據(jù),如需更改則復(fù)制數(shù)據(jù)副本來(lái)更改,并返回新數(shù)據(jù))
  • 純函數(shù) (沒有副作用,例如不要設(shè)置全局狀態(tài),不更改應(yīng)用程序狀態(tài),函數(shù)參數(shù)不可變)
  • 數(shù)據(jù)轉(zhuǎn)換 (不改變現(xiàn)有數(shù)據(jù),返回新的數(shù)組或?qū)ο螅鏏rray.prototype.join)
  • 高階函數(shù) (將函數(shù)作為參數(shù)或者返回函數(shù),或兩者都有;可操縱其它函數(shù))
  • 遞歸 (滿足一定條件之前調(diào)用自身的技術(shù))
  • 組合 (將較小的函數(shù)組合成更大的函數(shù),最終得到一個(gè)應(yīng)用程序)
17、Set、WeakSet、Map、WeakMap
  • Set
    • 成員唯一、無(wú)序且不重復(fù)
    • [value, value],鍵值與鍵名是一致的(或者說只有鍵值,沒有鍵名)
    • 可以遍歷,方法有:add、delete、has
  • WeakSet
    • 成員都是對(duì)象
    • 成員都是弱引用,可以被垃圾回收機(jī)制回收,可以用來(lái)保存DOM節(jié)點(diǎn),不容易造成內(nèi)存泄漏
    • 不能遍歷,方法有add、delete、has
  • Map
    • 本質(zhì)上是鍵值對(duì)的集合,類似集合
    • 可以遍歷,方法很多可以跟各種數(shù)據(jù)格式轉(zhuǎn)換
    • 鍵與內(nèi)存地址綁定,簡(jiǎn)單類型(number、string、boolean)的值嚴(yán)格相等則同一鍵,undefined與null不同鍵,NaN不嚴(yán)格等于自身但Map視為同一鍵
  • WeakMap
    • 只接受對(duì)象作為鍵名(null除外),不接受其他類型的值作為鍵名
    • 鍵名是弱引用,鍵值可以是任意的,鍵名所指向的對(duì)象可以被垃圾回收,此時(shí)鍵名是無(wú)效的
    • 不能遍歷,方法有g(shù)et、set、has、delete

18、布爾類型轉(zhuǎn)換

數(shù)據(jù)類型 轉(zhuǎn)換成true的取值 轉(zhuǎn)換成false的取值
Undefined 無(wú) undefined
Boolean true false
Object 非null時(shí)都為true null
Number 任何非零數(shù)字值(包括無(wú)窮大) 0和NaN
String 非空字符串 ""(空字符串)

19、位運(yùn)算符

&與,|或,~取反,^異或,>>左移,<<右移。

20、ES5的類 vs ES6 class

  1. 提升
    • class聲明會(huì)提升,但不會(huì)初始化賦值。Foo進(jìn)入暫時(shí)性死區(qū),類似let、const聲明變量
    • es5的函數(shù)會(huì)進(jìn)行函數(shù)提升
  2. class聲明內(nèi)部會(huì)啟動(dòng)嚴(yán)格模式
  3. class的所有方法(包括靜態(tài)方法和實(shí)例方法)都是不可枚舉
  4. class 的所有方法(包括靜態(tài)方法和實(shí)例方法)都沒有原型對(duì)象 prototype,所以也沒有[[construct]],不能使用 new 來(lái)調(diào)用
  5. 必須使用 new 調(diào)用 class
  6. class 內(nèi)部無(wú)法重寫類名。
  7. 繼承
    • ES5是通過call或者apply回調(diào)方法調(diào)用父類
    • ES6的繼承實(shí)現(xiàn)在于使用super關(guān)鍵字調(diào)用父類

21、async/await

  • await是一個(gè)讓出線程標(biāo)志。
  • await后面的表達(dá)式會(huì)先執(zhí)行一遍。
  • 然后將await后面的代碼加入到microtask中
  • 然后跳出整個(gè)async函數(shù)。

async本身是promise+generator的語(yǔ)法糖。所以await后面的代碼是miscrotask。

22、異步編程

  1. 回調(diào)函數(shù)
  2. 事件監(jiān)聽
  3. Promise對(duì)象
  4. Generator
  5. async/await

23、call & apply

作用一樣,區(qū)別在于傳參的不同

  • 第一個(gè)參數(shù)都是指定函數(shù)體內(nèi)this的指向
  • 第二個(gè)參數(shù)開始不同
    • apply是傳入帶下標(biāo)的集合、數(shù)組或類數(shù)組,apply把它傳給函數(shù)作為參數(shù)
    • call從第二個(gè)開次傳入的參數(shù)是不固定的,都會(huì)傳給函數(shù)作為參數(shù)
    • call比apply的性能都要好,call傳參數(shù)正式內(nèi)部所需要的格式(在ES6中可用解構(gòu)語(yǔ)法替代apply的傳參方式)
實(shí)現(xiàn)bind、call、apply
Function.prototype.myBind = function(ctx,...arg1){
    var fn = this
    return function(...arg2){
        return fn.call(ctx,...arg1,...arg2);
    }

}
Function.prototype.myCall = function(ctx,...args){
    const fn = Symbol('fn');
    ctx[fn] = this
    const result = ctx[fn](...args)
    Reflect.deleteProperty(ctx,fn);
    return result
}
Function.prototype.myApply = function(ctx,args){
    const fn = Symbol('fn');
    ctx[fn] = this
    const result = ctx[fn](...args)
    Reflect.deleteProperty(ctx,fn);
    return result
}

24、箭頭函數(shù)

  • 沒有this,從作用域鏈的上一層繼承this(無(wú)法使用call/apply/bind)
  • 不綁定arguments
  • 不可使用yield(不能作為Generator)
  • 不可使用new命令(無(wú)this,無(wú)prototype:new命令執(zhí)行時(shí)需要將構(gòu)造函數(shù)的prototype復(fù)制給新的對(duì)象__proto__)

25、判斷瀏覽器

function myBrowser() {
  var userAgent = navigator.userAgent; //取得瀏覽器的userAgent字符串  
  var isOpera = userAgent.indexOf("Opera") > -1;
  if (isOpera) {
    return "Opera"
  }; //判斷是否Opera瀏覽器  
  if (userAgent.indexOf("Firefox") > -1) {
    return "Firefox";
  }  //判斷是否Firefox瀏覽器  
  if (userAgent.indexOf("Chrome") > -1) {
    return "Chrome";
  }   //判斷是否Google瀏覽器  
  if (userAgent.indexOf("Safari") > -1) {
    return "Safari";
  } //判斷是否Safari瀏覽器  
  if (userAgent.indexOf("compatible") > -1 && userAgent.indexOf("MSIE") > -1 && !isOpera) {
    return "IE";
  }; //判斷是否IE瀏覽器  
}

26、垃圾回收機(jī)制

沒有被引用的對(duì)象就是垃圾,要被清除。幾個(gè)對(duì)象引用形成一個(gè)環(huán),相互引用,但是訪問不到的,也是垃圾。

  • 標(biāo)記清除
    • 標(biāo)記階段:把所有活動(dòng)對(duì)象做上標(biāo)記
    • 清除階段:把沒有標(biāo)記(非活動(dòng)對(duì)象)銷毀
  • 引用計(jì)數(shù)
    • 跟蹤記錄每個(gè)值被引用的次數(shù)
    • 當(dāng)引用次數(shù)0時(shí),垃圾回收器下次運(yùn)行時(shí),就會(huì)是否次數(shù)為0的值所占用的內(nèi)存

27、塊級(jí)作用域與函數(shù)聲明

// 瀏覽器的 ES6 環(huán)境
function f() { console.log('I am outside!'); }

(function () {
  if (false) {
    // 重復(fù)聲明一次函數(shù)f
    function f() { console.log('I am inside!'); }
  }

  f();
}());
// Uncaught TypeError: f is not a function

為了兼容舊代碼,瀏覽器的實(shí)習(xí)可以不遵守規(guī)定(塊級(jí)作用域之中,函數(shù)聲明語(yǔ)句的行為類似于let,在塊級(jí)作用域之外不可引用):

  • 允許在塊級(jí)作用域內(nèi)聲明函數(shù)。
  • 函數(shù)聲明類似于var,即會(huì)提升到全局作用域或函數(shù)作用域的頭部。
  • 同時(shí),函數(shù)聲明還會(huì)提升到所在的塊級(jí)作用域的頭部。

相當(dāng)于如下:

 瀏覽器的 ES6 環(huán)境
function f() { console.log('I am outside!'); }
(function () {
  var f = undefined;
  if (false) {
    function f() { console.log('I am inside!'); }
  }

  f();
}());
// Uncaught TypeError: f is not a function
28、表示一個(gè)字符的方式(6種)
'\z' === 'z'  // true
'\172' === 'z' // true
'\x7A' === 'z' // true
'\u007A' === 'z' // true
'\u{7A}' === 'z' // true
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 第3章 基本概念 3.1 語(yǔ)法 3.2 關(guān)鍵字和保留字 3.3 變量 3.4 數(shù)據(jù)類型 5種簡(jiǎn)單數(shù)據(jù)類型:Unde...
    RickCole閱讀 5,543評(píng)論 0 21
  • 單例模式 適用場(chǎng)景:可能會(huì)在場(chǎng)景中使用到對(duì)象,但只有一個(gè)實(shí)例,加載時(shí)并不主動(dòng)創(chuàng)建,需要時(shí)才創(chuàng)建 最常見的單例模式,...
    Obeing閱讀 2,321評(píng)論 1 10
  • 概要 64學(xué)時(shí) 3.5學(xué)分 章節(jié)安排 電子商務(wù)網(wǎng)站概況 HTML5+CSS3 JavaScript Node 電子...
    阿啊阿吖丁閱讀 9,880評(píng)論 0 3
  • js基礎(chǔ) 1.javaScript的數(shù)據(jù)類型有什么 基本數(shù)據(jù)類型:Undefined、Null、Boolean、N...
    說書人_子將閱讀 589評(píng)論 0 0
  • JavaScript語(yǔ)言精粹 前言 約定:=> 表示參考相關(guān)文章或書籍; JS是JavaScript的縮寫。 本書...
    微笑的AK47閱讀 663評(píng)論 0 3

友情鏈接更多精彩內(nèi)容