Review JavaScript

紅寶書

綜合

  • script加載js會阻塞渲染,標籤中 defer 指異步加載js,在文檔load以後按順序執行。async指異步加載,加載完當即執行,不保證順序
  • <noscropt>用來在不支持腳本的瀏覽器顯示內容
  • js 選中文字:
    • 一、document.createRange()
    • 二、range.selectNodeContents(element);
    • 三、window.getSelection() .removeAllRanges() .addRange(range)
      • 四、document.execCommand("copy");// 複製
  • 數組隊列與棧方法
    • .push(a, b, …) 在數組末尾推動數個值
    • .pop() 數組末尾刪除一個值並返回這個值
    • .shift() 數組開頭刪除一個值並返回這個值
    • .unshift(a, b, …) 在數組開頭推動數個值
  • 數組的 sort 方法默認是把成員調用 .toString() 而後比較字符,會有bug,最好傳一個比較函數
  • 數組與字符串截取:
    • 一、slice(start, end),返回一個新的數組(字符串), 不會修改原來的 — 數組/字符串
    • 二、substring(start, end) 提取兩個指定index之間的字符, 包括start不包括end, 不接受負的參數。 — 字符串
    • 三、splice(start, length, p1, …., pn)向/從數組中添加/刪a除項目, 而後返回被刪除的項目。會改變原來的數組。— 數組
    • 四、substr(start, length) — 字符串
  • 函數沒有重載,本身判斷 arguments。arguments.callee指向函數本身,遞歸時用到。arguments.callee.caller指調用函數的函數
  • 在讀取基本類型時,至關於爲基本類型建立了對應的基本包裝類對象,方便數據操做,如:2.toString()。操做基本類型值的語句一旦完成就馬上銷燬建立的包裝對象
  • 圖片預加載能夠new Image() = document.images[i].src
  • 圖片懶加載:
    • 一、取可視區域高度:document.documentElement.clientHeight
    • 二、取當前已經往下滾動了的距離:document.documentElement.scrollTop
    • 三、取當前元素距離頂部的距離:element.offsetTop
    • 四、當offsetTop < clientHeight + scrollTop 就證實當前元素在視窗底部以上(也可能已是視窗訂不上面看不到了),設置當前元素的src進行加載

對象及原型

  • 對象再也不引用就設置爲 null,解除引用,讓垃圾回收
  • Object.defineProperty, .defineProperties定義對象屬性
    • 可配置,可遍歷,(可寫,值) 或者 (get,set)
  • Object.getPrototypeOf 與 __proto__ 同樣用於去對象的原型
  • P.prototype.isPrototypeOf(obj):用於測試 obj 是否存在於P的原型鏈上
  • 構造函數作的事情:
    • 一、建立一個新對象
    • 二、將本身的做用域this賦給新對象
    • 三、執行代碼(爲這個新對象添加屬性)
    • 四、返回新對象
  • 繼承最優解:
    • 一、在子類裏執行父類.call(this),爲的是調用父類的構造方法並綁定到本身的this上
    • 二、子類的prototype繼承父類的prototype,若是直接指向父類的prototype會致使子類修改本身的prototype會影響父類的實例
  • 構造函數不加new當普通函數執行,就會將本身的this綁定所屬上下,執行一波賦值操做
  • with與try對原型鏈影響:延長做用域鏈
    • 一、with 將接受的參數添加到做用域鏈最前端
    • 二、try 建立一個包含被拋出錯誤對象的聲明的對象
    • 三、只要有finally就確定執行,哪怕try或者catch裏有 return
    • 四、window.onerror = function(msg, url, line){} return true 至關於對整個文檔的catch
    • 五、assert 斷言:一場處理高級方式,其實就是函數傳bool和msg進,爲false驗證失敗就拋錯
  • obj.hasOwnProperty(key):實例屬性,key in obj:無論是實例仍是原型鏈上的屬性。二者結合使用能夠判斷屬性是對象的仍是原型的。
Object.getOwnPropertyNames(obj):實例全部的屬性,不管是否可枚舉
Object.keys(obj):獲取實例的可枚舉的屬性
  • Object.create 第一個參數是要集成的對象,第二個與defineProperties參數同樣,用來新增或覆蓋父類屬性
  • 對象集成實踐
    • 一、傳統方式:A(),B(),B.prototype = new A() //注意這裏子類的 prototype是父類的實例。缺點是給子類構造函數傳參,父類構造函數,沒辦法執行
    • 二、強化模式:A(p),B(p){A.call(this,p)},B.prototype = new A() //會執行兩次 A()
    • 三、牛逼模式:A(p),B(p){A.call(this,p)},B.prototype = Object.create(A.prototype) // 注意這裏的prototype只能是集成,若是直接指向A.prototype就不是集成了,改子類會直接影響到父類

函數

  • 每一個函數都有本身的執行環境,執行環境有一個關聯的變量對象,保存了環境中定義的全部變量和函數。瀏覽器裏最外層的執行環境是window。
  • 當執行流進入一個函數就會把函數的執行環境推動一個棧,函數執行後彈出
  • 當代碼在一個執行環境中執行時,會建立一個做用域鏈對象,若是執行環境是函數,做用域鏈最前端上就是函數的活動對象(一開始只包含arguments對象)。做用域鏈是爲了執行環境有序訪問變量和函數
  • 內部函數在搜索this和arguments這兩變量時只會搜到其活動對象爲止
  • 閉包:當外層函數執行後,返回的匿名函數的做用域鏈仍然在引用這個活動對象,致使外層沒被銷燬。
要注意閉包不用的時候設爲null,釋放內存
  • 匿名函數的執行具備全局性
  • 函數內部定義了函數就是閉包
  • 當即執行匿名函數能夠減小閉包占用內存問題,由於沒有指向匿名函數的引用,函數執行後就會釋放
  • 閉包和私有變量會致使在做用域鏈上多差幾個層次,影響性能

正則

  • regexp.exec(string) 返回一個匹配結果數組
  • regexp.test(string) 返回一個是否匹配的BOOL值
  • string.match(regexp) 同regexp.exec,返回一個匹配結果數組
  • string.search(regexp) 返回字符串中第一個匹配項的索引
  • string.replace(regexp, str/Fun),第二個參數是字符串,如:xxx($1)用來取正則()匹配值並替換等等。第二個函數還能夠是函數,通過更精細的操做return
  • string.split(regexp) 將字符串切割成數組

BOM

  • 全局對象不能經過 delete 操做刪除,定義在window上的能夠
  • self始終指向window
  • 窗口大小:
    • outerWidth, outerHeight:瀏覽器窗口大小
    • innerWidth, innerHeight:視口viewport大小
    • 在chrome中其實都是viewport大小
  • document.documentElement.clientWidth, .clientHeight:頁面可見區域大小
  • location.assign(url),調用 window.location = url和location.href = url至關於調用了assign
    • 每次修改location的屬性(search,hostname,pathname,port)都會從新加載,hash屬性除外但有歷史記錄
    • location.replace跳轉頁面,另history.replaceState是不刷新頁面改url和歷史記錄且必須同源
  • 客戶端檢測:能力檢測,怪癖檢測,用戶代理檢測

DOM

  • childNodes 與 children不一樣,children沒有文本和空白節點。firstChild, firstElementChild
  • DocumentFragment文檔片斷,能夠把node添加到這裏面,再把這個片斷插入文檔
  • Nodes包含不少類型經常使用的:Element, Text, Comment, DocumentFragment
  • 建立<script>,給src屬性或者給其appendchild creatTextNode(‘要執行的代碼’),css就建立link標籤
  • 元素的dataset屬性能夠訪問data-開頭的自定義屬性,getAttribute() 能夠獲取任意屬性,常規屬性能夠直接 . 語法獲取
  • classList 獲取 class的類數組 add,contains, remove, toggle
  • outerHTML 包括本身,innerHTML不包括本身
  • html優化,使用innerHTML代替循環建立dom,替換前記得手動刪除html用到的js函數與屬性,否則html銷燬了js確一直被佔用
  • scrollIntoView() 把元素滾到當前屏幕
  • xmlns 命名空間,不懂,大概是在xml中區別svg等其餘的吧,否則只會顯示XML標記或通知XML中有錯誤

事件

  • 事件處理函數裏this只元素自己,即event.currentTarget,target是觸發事件的對象,currentTarget是監聽函數的對象
  • ele.onclick=的函數執行時冒泡,可是這是與同是使用 .onclick 的語法比,與addEventListener比是誰先定義誰先執行
  • 直接在html裏指定onclick屬性是誰先定義誰先執行,基本上就是捕獲了
  • 在本身元素上同事監聽冒泡和捕獲,哪一個先註冊就先執行哪一個
  • event.preventDefault() 來阻止事件的默認行爲,如阻止<a>的click。可是隻有e.cancelable爲true時才能阻止
  • event.stopPropagation阻止事件的傳播,即阻止捕獲或冒泡
  • event.eventPhase 看事件是哪一個階段 1捕獲,2自身,3冒泡
  • blur與focus不冒泡,focusin與focusout冒泡,不冒泡的會先於父類的捕獲執行
  • 鼠標位置,clientX,clientY和pageX,pageY和screenX,screenY
  • keydown, keyup事件有 event.keyCode 對應鍵盤按鈕
  • DOMContentLoaded: DOM樹完成事件,比window.onload快
  • event.persisted爲true時能夠配合pageshow, pagehide使用
  • createEvent與dispatchEvent新建和觸發事件,e.initMouseEvent("click",false,false);
  • event.isTrusted:事件被用戶調用時爲可信事件,若是是被腳本語言調用,爲不可信事件
  • -事件優化
    • 缺陷:
      • 處理函數多會佔用內存
      • 必須實現指定全部處理方法致使dom遍歷多,延遲頁面就緒時間
    • 優化方法:
      • 事件委託(捕獲/冒泡)
      • 移除事件程序,好比innerHTML會移除dom,但事件監聽仍與dom保持引用關係
  • addEventListener第三個參數不只是bool值,還支持對象
    • capture 表示listener會在該類型的事件捕獲階段傳播到該EventTarget 時觸發。
    • once 表示listener在添加以後最多隻調用一次。若是是 true,listener會在其被調用以後自動移除。
    • passive 表示listener永遠不會調用preventDefault()。若是listener仍然調用了這個函數,客戶端將會忽略它並拋出一個控制檯警告。

表單

  • input和textarea 選中文本,.select(),.setSelectionRange(start,end) — 這個必須先focus
  • beforecopy,copy,beforecut,cut,paste事件,copy能夠禁止別人複製文本
event.clipboardData setData、getData、clearData
  • H5屬性:
    • require; type=「email」/「url」;
    • type=「number」時,min,max.step
    • pattern 接受一個正則表達式
    • checkValidity(): 全部表單字段都有
    • novalidate:禁用驗證
  • 富文本編輯:
    • 一、iframe設置 designMode = 「on」
    • 二、普通元素設置 contenteditable
  • document.execCommand() 能夠接受不少指令,包括複製剪切粘貼刪除選中等等富文本操做

canvas

  • context.toDataURL(「image/png」) 能夠取得畫布中的圖像(圖像不能來自其餘域,不懂)
  • fillStyle, strokeStyle, strokeReact, clearReact, fillReact, fillText, strokeText
  • 繪製路徑以前必須先調用:beginPath()
  • 變換:rotate, scale, translate, transform, setTransform
  • 繪製圖像:context.grawImage(imgElement/canvas, x, xx, …)
  • 陰影:shadowOffsetX, shadowOffsetY, shadowBlur, shadowColor
  • 漸變:
    • 一、content.createLinearGradient(sx, sy, ex, ey) 建立一個漸變區域 gradient
    • 二、gradient.addColorStop(0, ‘red’), gradient.addColorStop(1, ‘blue’)等添加漸變色
    • 三、context.fillStye = gradient
  • 模式:
    • 一、context.createPattern(imgElement, 「repeat/repeat-x/repeat-y/norepeat」)建立 pattern
    • 二、context.fillstyle = pattern
  • 圖像數據
    • 一、context.getImageData(x, y, w, h)能夠獲取 imageData,其中imageData.data是顏色數組,可改
    • 二、context.putImageData(imageData, x, y)能夠把imageData寫到context去
  • 合成:
    • 一、context.globalAlpha能夠設置全局透明度
    • 二、context.globalCompositeOperation 表示後繪製的圖形怎樣與先繪製的圖形結合

WebGL與ArrayBuffer

  • 所謂 WebGL,就是指瀏覽器與顯卡之間的通訊接口,爲了知足 JavaScript 與顯卡之間大量的、實時的數據交換,它們之間的數據通訊必須是二進制的,而不能是傳統的文本格式。
  • ArrayBuffer是一段內存中連續的二進制數
  • TypedArray與DataView只是試圖,自己不包含數據。ArrayBuffer只能由試圖操做
  • TypedArray成員都是同一個數據類型, TypedArray(buffer, byteOffset=0, length?)
同一個ArrayBuffer對象之上,能夠根據不一樣的數據類型,創建多個視圖。
視圖還能夠不經過ArrayBuffer對象,直接分配內存而生成:const f64a = new Float64Array(8);
參數也能夠是一個普通數組:new Uint8Array([1, 2, 3, 4]);
普通數組的操做方法和屬性,對 TypedArray 數組徹底適用。除了concat
  • DataView成員能夠是不一樣的數據類型, setXXX(index, data, true/undefined)用來寫入數據
  • WebGL再看

HTML5

  • postMessage(data, 「origin」), addEventListener("message」, e => {})
  • history:
    • .pushState(data, 「name」, url), .replaceState(data, 「name」, url)
    • 返回時會監聽到 popstate,能夠在這裏把數據重置成以前的狀態
    • 確保pushState建立的假URL在服務器上有對應真的,否則刷新會404

拖放

  • 被拖對象:dragstart, drag, dragend
  • 被放的地方:dragenter, dragover, dradleave, drop
  • 阻止被放對象的dragenter和dragover默認時間就能夠觸發drop事件
  • event.dataTransfer對象保存了被拖對象向被放對象傳遞的 text/url或者MIME 數據
    • 能夠在 dragstart裏 .setData(), 在 drop 事件中讀取
    • .setDragImage(el, x, y) 能夠設置在鼠標下顯示的圖像
    • .dropEffect:被拖對象可以執行那種放置行爲,必須搭配 effectAllowed,在dragenter設置能夠控制鼠標顯示
    • .effectAllowed:表示容許拖動元素的那種dropEffect // 這兩玩意好像沒什麼效果
  • 標籤的 draggable 屬性能夠設置拖動
  • event.dataTransfer.files 能夠獲取拖拽過來的文件

XML

  • new DOMParser().parseFromString(str) 把xml字符串轉爲DOM文檔
  • new XMLSerializer().serializeToString(xmldom) 把dom轉爲xml字符串

JSON

  • json 中不支持 js 的undefined,函數,變量,對象實例,對象鍵名必須加雙引號
  • json簡單值能夠是 5, 「aaa」之類直接值
  • json裏必須使用雙引號,單引號會致使語法錯誤
  • JSON.stringify(obj, Array / Function, n)
    • 第二個參數用來過濾,只顯示數組裏包含的屬性或返回函數返回值, 若是函數返回undefined就是忽略相應的屬性
    • 第三個是費否縮進,若是是數字就是縮進的空格數(也就是會換行,換行後縮進多少),若是是字符串,縮進就用這個代替空格
  • 解析順序:
    • 一、若是存在toJSON()方法且能取到有效值就取值,不然返回對象自己
    • 二、第1步的值傳入第二個參數
    • 三、序列化第二部返回的值
    • 四、使用第三個參數格式化
  • JSON.parse(str, Function),第二個參數是函數也接受key和val兩個參數,用來處理返回值,若是返回undefined就是刪除這個字段
  • JSON更輕量,簡化了表示複雜數據結構。XML建立DOM、索引值都很麻煩

AJAX與Comet

  • 步驟:
    • 一、var xhr = new XMLHttpRequest()
    • 二、xhr.onreadystatechange = Function, xhr.readyState有0~4一共5個狀態,=4是完成,每次變化都會觸發onreadystatechange
    • 三、xhr.open(type, url, bool)第三個參數是否異步發送
    • 四、xhr.send(data)
    • 五、xhr.abort() //取消
  • xhr對象有:responseText, responseXML, status, statusText等屬性
    • .overrideMimeType能夠重寫返回的MimeType
  • header:
    • Accept和三個Accpet-xxx(字符,編碼,語言)
    • Connection 與服務鏈接類型,keep-alive/close
    • Cookie
    • Host
    • Referer:發出請求的頁面URI
    • User-Agent
  • xhr.setRequestHeader(name, value) 能夠設置頭
  • xhr.getRequestHeader(name) 能夠獲取服務響應的header的具體值
    • .getAllRequestHeaders() 獲取全部,是多行文本內容
  • 把header裏Content-Type設置爲application/x-www-form-urlencode能夠模仿發送表單提交
    • new FromData(formElement) 或者.append(name, val),send(data)能夠沒必要手動設置Content-Type
  • loadstart, progress, error, abort, load, loadend
    • progress能夠監聽進度,其參數event有:
    • .lengthComputable(進度信息是否可用)
    • position (已經接收的字節數)
    • totalSize(Response Header 裏 Content-Length預期字節數)
  • Comet是服務保持鏈接不斷周性的想瀏覽器發消息,xhr.readyState週期性的變爲3,整個頁面只有一個http鏈接
SSE 服務發送事件

跨域

  • 原理使用自定義的http頭部與服務器溝通,從而決定應不該該響應
    • 一、web發送請求時,給header添加一個Origin,這是瀏覽器作的,本身不要弄
    • 二、服務在Access-Control-Allow-Oringin裏面設置容許的Origin或 *
      • Access-Control-Allow-Methods,
      • Access-Control-Allow-Headers,
      • Access-Control-Max-Age,
      • Access-Control-Allow-Credentials
    • 三、請求頭和響應都不包含cookie
    • 四、不能使用setRequestHeader
    • 五、getAllRequestHeaders 獲取到的是空字符串
  • 預檢請求(Preflighted Request)
    • 一、簡單請求不會觸發,如:GET, HEAD
    • 二、默認跨域請求不帶cookie,設置withCredentials,且服務設置Access-Control-Allow-Crendenttials
  • 其餘跨域技術:
    • 一、new Image()對象
    • 二、JSONP 動態建立<script>給url拼一個回調函數名。與image比,能直接訪問響應文本。缺點:會夾雜惡意代碼,狀態不肯定
    • 三、websocket:open(),send(), .close(),onmessage,onopen,onerror,onclose

安全

  • CSRF:本身沒權限僞裝有權限去調接口
    • 解決:一、SSL,二、驗證碼
    • 徒勞:一、POST代替GET,二、URL來源能夠被僞造,三、cookie 也容易僞造

高級技巧

  • 利用Object.prototype.toString檢測數據類型,代替instanceof,後者在跨窗口有問題
  • 做用域安全的構造函數,多一層instanceof判斷,避免污染全局對象
  • 惰性載入函數:
    • 一、調用函數時走了一遍 if 語句後將本身(函數)=另外一個之後會執行的正確的函數
    • 二、加載時就用當即執行函數判斷 if 而後返回正確的函數
  • 綁定this:
    • bind:返回一個綁定做用域的函數,自身不變。第二個及後面的參數做爲柯理化預設置的參數
    • call:在一個做用域上執行,第二個及後面的參數做爲函數的參數
    • apply:在一個做用域上執行,第二個參數一個數組,包含了傳給函數的參數
  • 柯理化:
    • 一、經過一個函數,爲這個函數設置好數個參數。好比爲其指定this
    • 二、ES5的 bind 實現了函數柯理化
  • 防篡改對象
    • 一、不可擴展對象:Object.preventExtensions(obj) 不能添加屬性,屬性能被刪除或者改值
    • 二、密封對象:Object.seal(obj) 不能添加屬性且不能被刪除,屬性能被改值
    • 三、凍結對象:Object.freeze(obj) 不能添加屬性且不能被刪除且不能改值
  • setTimeout能夠切割運算量大的內容,如循環執行數組,就循環放進setTimeout
  • 節流:使用 setTimeout 確保每次操做後隔一段時間後執行,避免瘋狂執行
  • EventBus:一個對象,向裏面添加一個 key 和監聽函數,這個對象觸發這個 key 並傳遞出參數。其實就是建立一個事件數組,裏面將 key 和引用了的函數對應,觸發的時候根據 key 搜索到這個函數並觸發他

離線存儲

  • cookie:
    • 一、4095B(5k不到),cookie httponly時js讀不到
    • 二、名,值,域,路徑,時間,安全標誌(SSL時才發cookie)
    • 三、cookie會在http請求頭中帶走,會影響性能,不要太大
    • 四、expires(GMT時間)已被max-age(秒)代替,不設置默認瀏覽器會話結束刪除
  • Storage:
    • 一、只能存儲string,存對象會變成調用對象的 toString()
    • 二、localStorage 要求同源
    • 三、大小 5M, chrome 和 safari 是 2.5M

性能

  • 做用域:
    • 避免全局查找
    • 避免with語句
    • 避免沒必要要的屬性查找
  • 優化循環:減值迭代,簡化終止條件,簡化循環體,使用後測試循環(do-while)
  • 展開循環:屢次調用函數比循環調用效率高
  • 避免雙重解釋:eval, function 和 setTimeout傳字符串
  • 最小化語句數:
    • 一、在一個聲明語句裏用逗號聲明多喝變量
    • 二、在一行進行 ++ / —操做,不要另起一步
    • 三、使用數組和對象字面量
  • 優化DOM交互:
    • 一、減小DOM更新,使用DocumentFragment文檔片斷一次性操做
    • 二、innerHTML代替creatElement,由於前者是系統建立DOM,後者是jsDOM調用
    • 三、使用事件代理(冒泡)減小頁面包含的處理程序
    • 四、HTMLCollection(DOM僞數組)類型每次取值都會查一遍,能夠複製到一個變量

新興API

  • 動畫:
    • 一、最佳間隔 17ms,可是setTimeout精度不高,chrome大約4ms,並且沒法知道屏幕重繪
    • 二、requestAnimationFrame會告訴瀏覽器有動畫了,瀏覽器在重繪屏幕前調用。第二個參數是dom,告訴他重繪發生在那個區域提升效率
    • 三、cancelAnimationFrame用來取消動畫
  • 頁面可見:document.hidden,document.visibilityState,document監聽 visibilitychange 事件
  • 定位:navigator.geolocation
    • 一、getCurrentPosition(successcb, errorcb, j是否高精度)
    • 二、watchPosition 跟蹤定位,參數同上
  • File API:
    • 一、File的屬性 name, size, type, lastModifedDate(上次被修改時間)
    • 二、方法:slice(start, end)
  • FileReader:異步讀取文件,相似 xhr
    • 一、readAsDataURL(base64),readAsText,readAsArrayBuffer,readAsBinaryString
    • 二、能夠讀file,也能夠讀blob
    • 三、事件:load, error, progress(lengthComputable, loaded,total),abort,loadend
    • 四、.abort()取消
  • 對象URL
    • 一、引用保存在File或Blob中的數據的URL,有時候只是爲了顯示本地圖片什麼的用URL就行,而沒必要js讀取整個文件
    • 二、window.URL.createObjectURL(file)返回一個url,記得window.URL.revokeObjectURL(url)釋放內存
  • XHR上傳文件:data = new FormData(), data.append(「name」, files[i]), xhr.send(data)
  • window.performance對象給出頁面加載和渲染的不少信息,懟性能優化有意義
  • Web Workers
    • 一、new Worker("./worker.js")
    • 二、outer.onerror,outer.onmessage,outer.postMessage(data),outer.terminate() //終止後任何事件都不觸發
    • 三、self.onmessage,self.postMessage,self.close() //與outer.terminate()同樣效果
    • 四、importScripts(a, b) 能夠引入js
    • 五、worker不能訪問DOM,this和self都指向worker對象自己,不少東西不能訪問,能訪問的有:XHR, 只讀location,setTimeout兄弟,navigator.onLine和ua等

ES6補充

Class

  • 類的內部全部定義的方法,都是不可枚舉的
  • 類和模塊的內部,默認就是嚴格模式
  • constructor方法默認返回實例對象(即this),徹底能夠指定返回另一個對象。
  • 實例的屬性除非顯式定義在其自己(即定義在this對象上),不然都是定義在原型上(即定義在class上)。
  • 類不存在變量提高
  • 若是在一個方法前,加上static關鍵字,就表示該方法不會被實例繼承,而是直接經過類來調用
  • 若是靜態方法包含this關鍵字,這個this指的是類,而不是實例,父類的靜態方法,能夠被子類繼承。
  • 類裏面使用 xx = xx 是實例屬性與方法,使用 name() 是原型鏈上的,二者不同,且前者須要babel之類
  • 子類必須在constructor方法中調用super方法,不然子類取不到this 會報錯,子類實例的構建,是基於對父類實例加工,只有super方法才能返回父類實例
    • ES5 的繼承,實質是先創造子類的實例對象this,而後再將父類的方法添加到this上面 (Parent.apply(this))。ES6 的繼承機制徹底不一樣,實質是先創造父類的實例對象this(因此必須先調用super方 法),而後再用子類的構造函數修改this。
  • super能夠做爲:父類構造函數,父類,父類原型對象。super.xx 執行的時候後,至關於 super.xxx.call(this),被調用的super.xx內的this是子類實例對象
  • 子類的__proto__屬性,表示構造函數的繼承,老是指向父類。子類prototype屬性的__proto__屬性,表示方法的繼承,老是指向父類的prototype屬性。
  • **ES5 是先新建子類的實例對象this,再將父類的屬性添加到子類上,因爲父類的內部屬性沒法獲取,致使沒法繼承原生的構造函數。ES6 是先新建父類的實例對象this,而後再用子類的構造函數修飾this,使得父類的全部行爲均可以繼承。
  • 拷貝時用 Object.getOwnPropertyDescriptor 與 Object.defineProperty,不要直接賦值。ES6模塊要保證導出的東西已經定義了,由於引用的文件裏再引用本身時不會執行,而是默認引用已存在,能夠用函數聲明解決這個問題,由於函數聲明會提高

Deorator修飾器

  • 修飾器對類的行爲的改變,是代碼編譯時發生的,而不是在運行時。
  • 修飾類:一個參數(目標類)
  • 修飾方法:三個參數(目標類的原型對象,屬性名,屬性描述)
  • 修飾器不能用於函數,由於函數會提高
  • babel-preset-stage-0

import與require

  • defer是「渲染完再執行」,async是「下載完就執行」。另外,若是有多個defer腳本,會按照它們在頁面出現的順序加載,而多個async腳本是不能保證加載順序的。瀏覽器對於帶有type="module"的<script>,都是異步加載,不會形成堵塞瀏覽器,即等到整個頁面渲染完,再執行模塊腳本,等同於打開了<script>的defer屬性。<script>的async屬性也能夠打開,這時只要加載完成,渲染引擎就會中斷渲染當即執行。執行完成後,再恢復渲染。
  • ES6 模塊之中,頂層的this指向undefined;CommonJS 模塊的頂層this指向當前模塊,這是二者的一個重大差別。arguments,require,module,exports,__filename,__dirname 在 ES6模塊中都不存在
  • CommonJS 模塊遇到循環加載時,返回的是當前已經執行的部分的值。最好是先引入後取值,避免require().xx

CommonJS與AMD

  • CommonJS 每一個文件就是一個模塊
  • require()獲取module時,Node會根據module.id找到對應的module,並返回module. exports
  • CommonJS是同步的,Node環境代碼在磁盤沒問題,瀏覽器就不行了,因此有AMD異步模塊定義
  • require.js會首先加載一個入口js文件,默認路徑與入口文件在一塊兒,模塊必須採用特定的define()函數來定義,若是這個模塊還依賴其餘模塊,那麼define()函數的第一個參數,必須是一個數組,指明該模塊的依賴性
  • require.config()接受一個配置對象,這個對象除了有前面說過的paths屬性以外,還有一個shim屬性,專門用來配置不兼容的模塊。具體來講,每一個模塊要定義(1)exports值(輸出的變量名),代表這個模塊外部調用時的名稱;(2)deps數組,代表該模塊的依賴性。
  • 過程:建立script標籤,模塊的URL添加到src裏,並綁定onload,onreadystatechange,onerror事件,將script插入DOM樹中開始加載。將模塊的URL,依賴列表,狀態等構建一個檢測對象數組,供第二步檢測用。
  • export, exports, module.exports 區別:
module.exports是CommonJS的。爲了方便,Node爲每一個模塊提供一個exports變量,指向module.exports
export是ES6的

問題

  • 有哪些跨域的方法,設置 document.domain有用嗎
在同一個一級域名下才行,子域1請求子域2,子域1吧document.domain=一級域meta標籤怎麼玩
  • encodeURI與encodeURIComponent 區別
encodeURI:任何保留字符都有特殊意義不會編碼,只編碼在uri不應出現的字符
encodeURIComponent:任何保留字符都是普通文本都必須編碼
  • 進程與線程的區別
一對多關係,一個進程有多個線程,線程只能屬於一個進程。
進程:相似一個應用程序,資源分配的最小單位。擁有獨立的堆棧空間和數據段,系統開銷比較大。
線程:多線程你懂的,程序執行的最小單位。擁有獨立的堆棧空間,可是共享數據段。
進程安全性比較高,也由於進程有獨立的地址空間,通訊麻煩。
多機分佈的用進程,多核分佈用線程
  • SVG 與 Canvas二者間的區別
SVG 是一種使用 XML 描述 2D 圖形的語言。
Canvas 經過 JavaScript 來繪製 2D 圖形。
SVG 基於 XML,這意味着 SVG DOM 中的每一個元素都是可用的。您能夠爲某個元素附加 JavaScript 事件處理器。
在 SVG 中,每一個被繪製的圖形均被視爲對象。若是 SVG 對象的屬性發生變化,那麼瀏覽器可以自動重現圖形。
Canvas 是逐像素進行渲染的。在 canvas 中,一旦圖形被繪製完成,它就不會繼續獲得瀏覽器的關注。若是其位置發生變化,那麼整個場景也須要從新繪製,包括任何或許已被圖形覆蓋的對象。
  • 默認狀況下, fetch 不會從服務端發送或接收任何 cookies。credentials: 'include'

其餘

  • preload 是告訴瀏覽器頁面一定須要的資源,瀏覽器必定會加載這些資源
  • prefetch 是告訴瀏覽器頁面可能須要的資源,瀏覽器不必定會加載這些資源
  • prerender預渲染雖然能夠提升頁面的加載速度,可是要確保該頁面百分百會被用戶在以後打開,不然就白白浪費資源去渲染

瀏覽器渲染引擎

  • 解析HTML構建DOM樹
  • 根據css樣式表,生成帶樣式數據的DOM渲染樹
  • 佈局階段(float,position,margin等)
  • 繪製階段(color,background,text-shadow等)
  • 觸發了階段3必然致使重排,而後重繪。因此要儘可能避免重排,重繪的代價要少點。

瀏覽器加載渲染過程

  • 自上而下加載,加載過程當中解析渲染
  • 加載中遇到外部css,img會發出異步請求,不會影響文檔加載
  • 加載中遇到js文件會掛起渲染進程,要等js加載和執行完,才恢復html渲染線程(由於js會修改DOM,document.write,解決方法是把js引用放在前)
  • css加載不影響js文件加載,但卻影響js文件的執行,即便js只有一行代碼也會形成阻塞(
 緣由:$(「#id」).width(),js執行前,css必須下載解析完成,這事css阻塞後續js的緣由。解決辦法:當js不須要依賴css時能夠放在頭部css前面
)
  • 不要在外部調用的js文件中調用運行時間較長的函數,若是必定要用,可使用setTimeout函數。
緣由:瀏覽器有以上五個常駐線程
    • 一、瀏覽器GUI渲染線程
    • 二、javascript引擎線程
    • 三、瀏覽器定時器觸發線程(setTimeout)
    • 四、瀏覽器事件觸發線程
    • 五、瀏覽器http異步請求線程(.jpg  這類請求)
這裏也涉及到 阻塞 的現象,當js引擎線程(第二個)進行時,會掛起其餘一切線程,這個時候三、四、5這三類線線程也會產生不一樣的異步事件(這句話不懂啊),因爲 javascript引擎線程爲單線程,因此代碼都是先壓到隊列,採用先進先出的方式運行,事件處理函數,timer函數也會壓在隊列中,不斷的從隊頭取出事件,這就叫:javascript-event-loop。
  • 現代瀏覽器存在 prefetch 優化,瀏覽器會另外開啓線程,提早下載js、css文件,須要注意的是,預加載js並不會改變dom結構,他將這個工做留給主加載。
  • 若是js不會改變文檔,能夠在script標籤加 defer 使瀏覽器先在加載後面的文檔javascript

    解析

  • html文檔解析生成解析樹即dom樹,是由dom元素及屬性節點組成,樹的根是document對象。
  • css解析將css文件解析爲樣式表對象。該對象包含css規則,該規則包含選擇器和聲明對象。
  • js解析由於文件在加載的同時也進行解析,詳看js加載部分。css

    渲染

  • 渲染最大的一個困難就是爲每個dom節點計算符合他的最終樣式。
  • #test p{ color:#999999}遍歷是自右向左,也就是先查詢到p元素,再找到上一級id爲test的元素。css解析時,生成的樣式對象,從樹的低端向上遍歷。
  • 樣式數據是很是大的結構,保存這樣是的數據是很耗內存
  • 選擇器迭代太深,形成太多的無用遍歷
  • 樣式規則涉及很是複雜的級聯,定義了規則的層次
  • 渲染過程當中,webkit使用一個標誌位標誌全部頂層樣式都已經被加載完畢,若是dom元素進行attach時,css元素並無被加載完畢,則放置佔位符,並在文檔中標記,當樣式表加載完畢,則從新進行計算。
說明:文檔的渲染仍是要等待頂層css加載完畢。
  • 頁面的渲染 須要首先生成dom樹,再由css生成CSSOM,最後兩個一塊兒生成render tree。html

event-loop

  • 全部同步任務在主線程執行棧執行
  • 主線程以外有一個任務隊列(事件/消息隊列),異步任務有告終果就會在任務隊列中添加一個事件,表示異步任務能夠進入執行棧了。只要指定過回調函數,事件發生時就會進入任務隊列,等待主線程讀取。任務隊列是先進先出的隊列,
  • 主線程中全部同步任務執行完以後會,讀取任務隊列,異步任務進入執行。因爲存在"定時器",主線程首先要檢查一下執行時間,某些事件只有到了規定的時間,才能返回主線程。
問題:主線程空的時候查看隊列,若是主線程一直不空隊裏裏的異步操做就一直延後嗎?
答:執行棧中的代碼(同步任務),老是在讀取"任務隊列"(異步任務)以前執行。
  • 定時器:setTimeout(fn,0)的含義是,指定某個任務在主線程最先可得的空閒時間執行,也就是說,儘量早得執行。它在"任務隊列"的尾部添加一個事件,所以要等到同步任務和"任務隊列"現有的事件都處理完,纔會獲得執行。要是當前代碼耗時很長,有可能要等好久,因此並無辦法保證,回調函數必定會在setTimeout()指定的時間執行。
    node-event-loop
  • process.nextTick方法能夠在當前"執行棧"的尾部----下一次Event Loop(主線程讀取"任務隊列")以前----觸發回調函數。
  • setImmediate方法則是在當前"任務隊列"的尾部添加事件,相似setTimeout(f,0);
  • 其實 異步隊列有兩個,一個大的一個小的,先佬小的再佬大的。因此正確的一次 Event loop 順序是這樣的
    • 執行同步代碼,這屬於宏任務
    • 執行棧爲空,查詢是否有微任務須要執行
    • 執行全部微任務
    • 必要的話渲染 UI
    • 而後開始下一輪 Event loop,執行宏任務中的異步代碼
    • node 環境有一個 process.nextTick 會先於其餘 microtask 執行。
相關文章
相關標籤/搜索