javascript篇--1.6萬字帶你回憶那些遺忘的JS知識點

發文前,小編想先對上一篇文章-css篇糾正錯誤以及針對文章提出的優化的小夥伴表示感謝,大家的每一個建議或意見都很寶貴🌻🌻。javascript

繼上兩篇文章html篇CSS篇以後,本篇文章對於常見的有關Javascript部分的內容進行了大體的整合。文中涉及的知識面仍是蠻廣的,小編在整理的時候也順道溫習了一遍。css

文章字數1.5萬+,篇幅比較長,仍是建議收藏吧,慢慢看。所謂溫故而知新,本篇文章做爲溫習知識點仍是挺有用的(尤爲是準備跳槽的小夥伴抱佛腳尤其有用哈哈哈哈)🥴。html

PS: 文中,爲了方便閱讀,小編一如既往作了分割線。java


1.🤪JavaScript 中 this 是如何工做的

首先,在js中,this是指正在執行的很熟的「全部者」,更確切的說,是指將當前函數做爲方法的對象。node

javascript中的this有一套徹底不用於其它語言的對this的處理機制。在如下五種狀況下,this的指向各不相同。linux

全局範圍

當在全局範圍內的時候,使用this將會指向全局對象(this->window)程序員

對象方法調用

這裏的this是在對象中的.當函數被保存爲對象的一個屬性時,成該函數爲該對象的方法,函數中this的值爲該對象。web

咱們先看個例子:ajax

const object = {
    a: 1, 
    func: function() {
        console.log(this.a)
    }
}

object.fun()  //1  (this->object)
複製代碼
function func() {
     console.log(this.a)
}
const object = {
    a: 1, 
    b: func
}

object.fun()  // 1 (this->object)
複製代碼

這裏的兩個this指向的是對象object,此時咱們能夠這麼理解,函數不管在對象內部或外部定義,實現的效果同樣。由於做爲對象的屬性的函數,對於對象來講是獨立的算法

可是須要注意有時候,對象中的也會存在this綁定丟失的問題,這也是咱們下面將的使用applycall調用模式。

使用apply或call調用模式

看下面例子:

function func() {
     console.log(this.a)
}
const object = {
    a: 1, 
    b: func
}
const fun = object.b;

fun()  // undefined
複製代碼

此時fun()打印出來的值並非對象中的1,而是undefined。由此可看出,此時的this指向的並非object對象。咱們再給代碼添加一個全局的a看看狀況:

function func() {
     console.log(this.a)
}
const object = {
    a: 1, 
    b: func
}
const fun = object.b;

var a = 2;
fun()  // 2
複製代碼

此時的func打印出來的是全局變量的值--2,說明此時的this是指向外部全局變量的。這種狀況主要是由由於this的隱式綁定致使的this綁定丟失

咱們能夠理解爲: 執行「 fun= object.b」以後fun的調用和object.b調用的結果是不一樣的,由於這個函數賦值的過程沒法把b所綁定的this也傳遞過

決絕方式:經過this的顯示綁定解決。

咱們能夠經過使用 callapply以及bind來解決,此時函數內的this將會被顯示設置爲函數調用的第一個參數。以下代碼:

function func() {
     console.log(this.a)
}
const object = {
    a: 1, 
    b: func
}
var a = 2;
const fun = object.b;

fun.call(object) 或者  fun.apply(object) 或者  const funb = fun.bind(object) ; funb() // 1
複製代碼

此時this指向的就是object內部的a,這就解決了this綁定丟失的問題。

🌈🌈注意

  • bind是提供了一個可執行的函數,可是自己並不會執行,須要咱們手動去執行;
  • callapply它們是提供了一個可當即執行的函數,在綁定this的同時,也會當即去執行該函數。這也是爲何咱們在最後一個bind方法中再次須要的單獨再調用一次funb()方法的緣由。

函數調用

此時的this也會指向全局對象。咱們也能夠這麼理解:當沒有明確的調用對象的時候,行數的this仍是在全局範圍內的,因此this會綁定到全局的window對象

調用構造函數

先看個例子:

function func() {
    this.b = a;
    console.log(b)
 }
 func(20);  // 20,此時的b是20
 
 const funb = new func(30)
 funb.b;  // 30
複製代碼

能夠看到,當執行new操做的時候,會建立一個新的對象,而且將構造函數的this指向所建立的新對象。

2.請解釋原型繼承 的原理

有關原型鏈以及其繼承的原理,小編在以前的文章毒雞湯中,在前面的部分圖文結合,已經作了比較詳細的介紹,有興趣的童鞋能夠去瞅瞅,小編這裏就不過多介紹了(又能夠偷懶了)。

3.什麼是閉包 (closure),如何使用它,爲何要使用它

有關閉包部分,亦是在毒雞湯中有所體現。

4. 同步 (synchronous) 和異步 (asynchronous) 函數的區別在哪裏

同步

同步(阻塞模式)指的是:當發送一個請求時,須要等待返回,而後才能發送另外一個請求。其有個等待的過程。此外,同步也能夠避免出現死鎖,讀髒數據的發生。

異步

異步(非阻塞模式)指的是:當發送一個請求時,不須要等待返回,能夠隨時發送下一個請求。其不須要等待。

區別: 最明顯的就是一個須要等待,一個不須要等待。

拓展: 在項目過程當中,能夠根據需求,來考慮功能是使用同步仍是異步。通常,有些功能爲了縮短用戶的等待時間,都會優先採用異步的方式;可是對於數據庫保存等操做,通常採用的是同步的方式。

5.JavaScript 宿主對象 (host objects) 和原生對象 (native objects) 以及內置(build-in objects)對象的區別

概念

  • 宿主對象: 宿主對象不是引擎的原生對象,而是由宿主框架經過某種機制註冊到js引擎中的對象;
  • 內置對象: 在引擎初始化階段就被建立好的對象,是原生對象的一個子集;
  • 原生對象: 除了內置對象以外,還包括了一些在運行過程當中動態建立的對象;

內容

  • 原生對象包括: Object, Function, Array, String, Boolean, Number, Date, RegExp, Error, EvalError, RangeError, ReferenceError, SyntaxError, Typerror, URLError等;
  • 內置對象包括: Global(全局對象), Math ;(注意全部的內置對象都是原生對象)
  • 宿主對象包括: 有宿主提供的對象,在瀏覽器中window對象以及其下邊的全部子對象(例如dom等),在node中是global以及其子對象,也包含自定義的類對象。

區別

  • 內置對象是原生對象的一個子集;前者總在引擎初始化階段就被建立好對象,然後者還包括了一些在運行過程當中動態建立的對象;
  • 宿主對象不是引擎的原生對象,而是有宿主框架經過某種機制註冊到js引擎當中的對象;

6.如下代碼有什麼區別:function Person(){}、var person = Person()、var person = new Person()

  • 第一: function Person(){}是聲明瞭一個名爲Person的函數;
  • 第二: var person = Person()是直接調用了Person函數,並將返回值做爲值賦值給變量person
  • 第三: var person = new Person()建立了一個Person實例對象;

7.什麼是變量聲明提高 (hoisting)

首先咱們先看個例子:

console.log(num); //undefined
var num = 5;
console.log(num) // 5
複製代碼

到這裏,有基礎的小夥伴可能看出來這是爲何了。沒錯,就是變量聲明提高!一個變量的生命週期包含3個階段

  • 聲明--從建立一個新的變量開始,例如:var num
  • 初始化--初始化變量給變量賦值,例如: num = 5
  • 使用--使用變量的值,例如console.log(num)

上面的例子其實等價於:

var num;
console.log(num); //undefined  由於變量num提高了,可是值並無提高,因此打印出來是undefined
num = 5;
console.log(num) // 5
複製代碼

🌈🌈注意: 若是變量是在函數做用域內,那麼它的做用域就是函數做用域。不然,它就是全局做用域。

拓展

拓展1之函數優先

函數聲明和函數表達式在語法上是的等價的,可是有一點不一樣的是,js引擎加載它們的方式不同。簡單來講就是:函數聲明會被提高到其做用域頂部,而函數表達式不會。

具體能夠看如下兩點:

  • 函數聲明會提高,可是函數表達式的函數體不會提高;
  • 函數是javascript的一等公民,當一個變量名和函數同名時,函數聲明優先變量聲明,而且會忽略同名的變量聲明。

拓展2之let,const和var

在此長話短說,總的來講就是letconst的聲明會造成塊級做用域,不存在變量提高且不能重複聲明同一變量(或常量)。而var聲明的變量會掛載在window上,存在變量提高且能夠命名重複。

8.什麼是 「use strict」; ? 使用其的優缺點

「use strict」-- 嚴格模式ES5添加的一種運行模式,目的是爲了是javascript在更嚴格的條件下運行。

優勢(設立的目的)

  • 消除js語法的一些不合理,不嚴謹之處,減小一些怪異行爲;
  • 消除代碼運行的一些不安全之處,保證代碼運行安全;
  • 提升編譯效率,增長運行速度;
  • 爲將來新版本的javascript作好鋪墊;

🌈🌈注意: 通過測試,目前IE6-9都不支持嚴格模式。

缺點

如今網站的js通常都會進行壓縮,壓縮過程當中,有些文件使用了嚴格模式,有些卻沒有。這種狀況下原本是嚴格模式的文件,被merge後,這個串就到了文件中間,不只沒有指示嚴格模式,在壓縮後也會浪費字節。

9.什麼是事件循環 (event loop)

javascript是單線程執行的,從上到下一次運行。在js中分爲兩個任務,宏任務和微任務。通常狀況下,首先執行的是宏任務(就是一般說的第一時間執行全部同步代碼),遇到微任務時,先加入隊列,宏任務執行完畢再執行微任務。微任務執行完畢以後再往下執行宏任務,執行完後再次執行全部微任務。

簡單的理解就是: 宏任務-> 微任務-> 宏任務 ->微任務;

終於詳細的執行機制,有興趣的小夥伴小編建議請移步至毒雞湯瞅瞅。

10.bind,call 和 apply 的區別

類似之處

  • 它們的第一個參數都是this要指向的對象;
  • 都是用來改變函數的this指向的;
  • 均可以利用後繼參數傳參;

區別

  • 執行方面:使用callapply以後函數可自動執行,可是使用bind須要手動執行;
  • 參數接收方面callapply接收的第一個參數是在其中運行函數的做用域,不一樣的是在接收的第二個參數時,apply接收的是一個數組,而call接收的是參數列表,須要跟函數保持一一對應。

🌈🌈注意callapply擴充了函數的做用域

應用場景

  • 若是不須要關心具體有多少參數被傳入函數的時候(或者參數較多狀況下),能夠選用apply
  • 若是肯定函數能夠接收多少個參數(或參數較少狀況下),而且想一目瞭然的表達形參和實參的對象關係的,能夠選用call;
  • 若是想未來再調用方法,不須要當即獲得函數的返回結果的,能夠選用bind;

🚚...................................................ᴅᴜᴅᴜ!

11. 🤥什麼是事件委託以及冒泡事件和默認事件如何阻止

概念事件冒泡是指嵌套最深的元素觸發一個事件,而後這個事件順着嵌套順序在父元素上觸發。而事件委託,是利用事件冒泡原理,讓本身所觸發的事件,讓其父元素代替執行。

冒泡阻止方式:使用event.cancelBubble = true或者event.stopPropgation()(低於IE9)。

默認事件阻止方式e.preventDefault();return false;

12. 如何檢查一個數字是否爲整數

比較簡單的方式是能夠將其數字對1進行取模,看看是否存在餘數。看如下代碼:

function isInt(number) {
    return number % 1 === 0;
};

console.log(isInt(2.1));  // false
console.log(isInt(2));  // true
複製代碼

13. 什麼是IIFE(當即調用函數表達式)

它是當即調用函數表達式(Immediately-Invoked Function Expression),簡稱爲IIFE。指的是函數被建立後當即執行。看下面代碼:

(function IIFE(){
 console.log( "Hello!" );
})();    

// "Hello!"
複製代碼

這種當即調用函數表達式通常應用於避免污染全局命名空間條件下。由於 IIFE(與任何其餘正常函數同樣)內部的全部變量在其做用域以外都是不可見的。

14. 原型設計模式

原型模式可用於建立新對象,可是它建立的並非初始化的對象,而是使用原型對象的值進行初始化的對象。原型模式也成爲屬性模式

原型模式在初始化業務對象是很是有用,業務對象中的值與數據庫的默認值相匹配。原型對象中的默認值被複制到新建立的業務對象中。目前js在構造新對象及其原型時使用了這個模式。

原型模式包含如下主要角色

  • 抽象原型類: 規定了具體原型對象必須實現的接口;
  • 具體原型類: 實現了抽象原型類的clone()方法,它是可被複制的對象;
  • 訪問類: 使用具體原型類中的clone()方法來複制新的對象;

15. jsonp的原理,以及爲何不是真正的ajax

Jsonp原理: 利用瀏覽器能夠動態的插入一段JS代碼並執行;

爲何不是真正的AJAX

  • 首先,ajaxjsonp在調用方式上雖然長得差很少(目的同樣,都是請求一個url,而後把服務器返回的數據進行處理),可是ajaxjsonp本質上是不一樣的東西;
  • 哪裏不一樣?核心不一樣!ajax的核心是經過XmlHttpRequest獲取非本頁內容,而jsonp的核心則是動態添加<script>標籤來調用服務器提供的js腳本;
  • 此外,須要注意的是,ajaxjsonp的區別不在因而否跨域。由於ajax經過服務端代理同樣能夠實現跨域,jsonp自己也不排斥同域的數據的獲取。還有就是jsonp是一種方式或者說是非強制協議,如同ajax同樣,它也不必定非要jsonp格式來傳遞數據;
  • jsonp只支持get請求,ajax支持getpost請求.

16. Javascript的事件流模型都有什麼

  • 「事件冒泡」: 當觸發一個節點的事件時,會從當前節點開始,依次觸發其祖先節點的同類型事件,直到DOM根節點。(逐級向上)
  • 「事件捕獲」: 當觸發一個節點的事件時,會從DOM根節點開始,依次觸發其祖先節點的同類型事件,直到當前節點自身。(逐級向下)
  • 「DOM事件流」dom同時支持兩種事件模型,但捕獲性事件先開始,從document開始也結束於documentdom模型的獨特之處在於文本也能夠觸發事件。簡單的說分爲三個階段:事件捕捉目標階段事件冒泡

17. new操做符具體幹了些啥

首先咱們須要明白的是:new關鍵字主要的做用仍是在於繼承

對於const a = new Foo();new乾的事情。以下代碼:

const obj = new Object();   // 聲明一個新的空對象obj
obj.__propto__ = Person.prototype;  // 讓obj的__proto__指向函數原型的prototype

Person.call(obj); // this指向obj對象

person = obj; // 將obj對象賦值給person對象
複製代碼

而後咱們來捋一捋,new一共經歷了幾個階段?(4個)

  • 建立一個空對象;
  • 設置原型鏈;
  • Functhis指向obj,並執行Func函數體;
  • 判斷Func(構造函數)的返回值類型;

18. js延遲加載的方式有哪些?

  • defer屬性(頁面load後執行):腳本會被延遲到整個頁面都解析完畢以後再執行。如果設置了defer屬性,就等於告訴瀏覽器當即下載,可是會延遲執行。注意defer屬性只適用於外部腳本文件。
  • async 屬性(頁面load前執行):爲了避免讓頁面等待腳本下載和執行,異步加載頁面和其餘內容。async一樣也只適用於外部文件(不會影響頁面加載,可是不能控制加載的順序)。
  • 動態建立DOM方式;
  • 使用jQuerygetScript()方法;
  • 使用setTimeout延遲方法;
  • js文件最後加載。

19. Flash和ajax各自的優缺點,以及在使用中如何取捨

  • 於Flash來講flash是個處理多媒體,矢量圖形以及訪問機器等;可是對於CSS,文本處理有不足,不容易被搜索;
  • 於Ajax來講AjaxCSS,文本處理有很好的支持,亦支持搜索;可是對多媒體,矢量圖形以及訪問機器等不足;

共同點

  • 與服務器的無刷新傳遞消息;
  • 能夠檢測用戶的離線和在線狀態;
  • 能夠操做DOM

20. Cookie在客戶機上是如何存儲的

cookies是服務器暫時放在咱們電腦裏的文本文件,好讓服務器來辨認咱們的計算機。

當咱們在瀏覽網站的時候,web服務器會先發送小部分資料放在咱們的計算機中,cookies會幫助咱們,將咱們在網站上打印的文字或一些選擇記錄下來,當咱們再次訪問同一個網站,web服務器會先檢查有沒有它上次留下的cookies資料。

如有,會依據cookies裏面的內容來判斷使用者,從而給咱們推出相應的網頁內容。

🚚...................................................ᴅᴜᴅᴜ!

21. 🤨什麼是Json

  • json是一種輕量級的數據交換格式;
  • 獨立於語言平臺,解析器和庫支持許多不一樣的編程語言;
  • 它的語法表示三種類型值:簡單值(numberstringbooleannull),數組,對象;

22. 線程與進程的區別

一個程序至少有一個進程,一個進程至少有一個線程。線程的劃分尺度小於進程,使得多線程程序的併發性高。這裏咱們能夠簡單的把進程理解成火車,線程理解爲車箱

區別

  • 線程在進程下運行,不能單獨運行(單純的一節節車箱沒法運行);
  • 一個進程能夠包含多個線程(一輛火車有不少車箱);
  • 不一樣進程之間的數據難以共享(列車在行駛時,乘客很難從一列火車換到另外一列火車);
  • 同一進程下的線程數據共享便捷(乘客在同一列火車上從一節車箱換到另外一節很方便);
  • 進程要比線程花費更多的計算機資源(車箱僅僅是跑,或者還要發動動力帶它跑,花的力氣更多);
  • 進程之間互不影響,可是同一個進程中要是有一個線程出現問題將致使整個進程有問題(一輛類車要是某一節車箱出問題好比起火,會致使火車暫停);
  • 進程能夠拓展到多機,而線程最多擴展到多核cpu。(不一樣的火車能夠開在不一樣的軌道上,而同一火車的車箱只能形式在當前火車行駛的軌道上);
  • 進程使用的內存地址能夠上鎖,即一個線程使用某些共享內存時,其餘線程必須等它結束才能使用這塊內存。(例如使用火車上的洗手間-「互斥鎖」);
  • 進程使用的內存地址能夠限定使用量(例如火車上的臥鋪,最多隻容許多少我的睡,若是安排滿了就須要等待,待有空牀位出來了才能進去--「信號量」);

23. 若是網頁內容須要支持多語言,須要考慮些什麼

  • 應用字符集的選擇,選擇utf-8編碼;
  • 語言書寫習慣以及導航結構;
  • 數據庫驅動型網站;

24. JavaScrip的一些編寫原則

  • 不要再同一行聲明多個變量;
  • 使用 ===!== 來作比較;
  • 使用字面量的方式來建立數組、對象,來代替new Array這種形式;
  • switch語句必需要帶default分支;
  • fon-in循環中的變量,用var關鍵字說明做用域,防止變量污染;
  • 儘量的用三元表達式代替if..else..條件語句;
  • 比較數據類型如下6中狀況是falsefalse""0nullundefinedNaN;其他的都是true
  • 數據類型檢測用typeof,對象類型檢測用instanceof
  • 異步加載第三方的內容; ...

25. 閉包是什麼,有什麼特性,對頁面有什麼影響

閉包是可以讀取其餘函數內部變量的函數,使得函數不被GC回收。可是濫用閉包,會致使內存泄漏;

26. document load 和document ready的區別

  • document load:是在結構和樣式,外部js和圖片加載完才執行js;
  • document ready: 是dom樹建立完成就執行的方法,原生是沒有這種方法的。

27. 如何中斷ajax請求

  • 設置超時時間讓ajax自動斷開;
  • 手動中止ajax請求,其核心是調用XML對象的abort方法,ajax.abort()

28. 宏任務和微任務

  • 宏任務: 當前調用棧中執行的任務稱爲宏任務。包括總體代碼scriptsetTimeoutsetInterval
  • 微任務: 當前(這次事件循環中)宏任務執行完,在下一個宏任務開始以前須要執行的任務爲微任務。包含回調事件,Promiseprocess.nextTick(node.js);

🌈🌈注意: 宏任務中的事件放在callback queue中,由事件觸發線程維護;微任務的事件放在微任務隊列中,由js引擎線程維護。

29. get和post的區別

  • get傳參方式是經過地址欄URL傳遞,是能夠直接看到get傳遞的參數,post傳參方式參數URL不可見,get把請求的數據在URL後經過?鏈接,經過&進行參數分割。psot將參數存放在HTTP的包體內;
  • get傳遞數據是經過URL進行傳遞,對傳遞的數據長度是受到URL大小的限制,URL最大長度是2048個字符。post沒有長度限制;
  • get回退不會有影響,post回退會從新進行提交;
  • get請求能夠被緩存,post不能夠被緩存;
  • get請求只URL編碼,post支持多種編碼方式;
  • get只支持ASCII字符,post提交沒有字符類型限制;
  • get請求的記錄會留在歷史記錄中,post請求不會留在歷史記錄;

30. 常見的http的響應碼及含義

(1)、1xx(臨時響應)

  • 100: 請求者應當繼續提出請求。
  • 101(切換協議) :請求者已要求服務器切換協議,服務器已確認並準備進行切換。

(2)、2xx(成功)

  • 200: 請求成功並返回正確接口結果;
  • 201: 表示資源被正確建立。
  • 202: 請求正確,但結果正在處理中,這時候客戶端能夠經過輪詢等機制繼續請求。
  • 203: 非受權信息,服務器已成功處理了請求,但返回的信息可能來自另外一個源;
  • 204: 無內容,服務器成功處理了請求,但沒有返回任何內容;
  • 205: 重置內容,服務器成功處理了請求,內容被重置;
  • 206: 部份內容,服務器成功處理了部分請求;

(3)、3xx(已重定向)

  • 300: 已經請求成功,可是有多個結果返回;
  • 301: 請求成功,可是資源被永久轉移;
  • 302: 臨時移動,請求的網頁暫時跳轉到其餘頁面,即暫時重定向;
  • 303: 使用get訪問新的地址來獲取資源;
  • 304: 請求的資源並無被修改過;
  • 305: 使用代理,請求者應該使用代理訪問該頁面;
  • 306: 臨時重定向,請求的資源臨時從其餘位置響應;

(4)、4xx(請求錯誤)

  • 400: 請求出現錯誤,好比請求頭不對等;
  • 401: 沒有提供認證信息。請求的時候沒有帶上 Token 等;
  • 402: 爲之後須要所保留的狀態碼;
  • 403: 請求的資源不容許訪問,無權限;
  • 405: 方法禁用,服務器禁用了請求中指定的方法;
  • 406:不接受,沒法使用請求的內容響應請求的頁面;
  • 407: 請求者須要使用代理受權;
  • 408: 服務器請求超時;
  • 409: 服務器在完成請求時發生衝突;
  • 410:請求的資源已永久刪除;
  • 411: 須要有效長度。服務器不接受不含有效內容長度標頭字段的請求;
  • 412: 服務器未知足請求者在請求中設置的其中一個前提條件;
  • 413: 請求實體過大,超出服務器的處理能力;
  • 414: 請求網址過長,服務器沒法處理;
  • 415: 請求格式不被請求頁面支持;
  • 416: 頁面沒法提供請求的範圍;
  • 417: 服務器未知足指望請求標頭字段的要求;

(5)、5xx(服務器錯誤)

  • 500: 服務器內部錯誤,沒法完成請求;
  • 501: 請求尚未被實現,服務器不具有完整的請求功能;
  • 502: 錯誤網關,服務器做爲網關或代理,從上游服務器收到無效響應;
  • 503: 服務不可用;
  • 504:網關超時,服務器做爲網關或代理。可是沒有及時從上游服務器收到請求;
  • 505HTTP版本不支持,服務器不支持請求中所用的HTTP協議版本。

🚚...................................................ᴅᴜᴅᴜ!

31. 😤IE和DOM事件流的區別

  • 從執行順序看IE採用的是冒泡型事件,而DOM是先捕獲後冒泡事件;

咱們能夠看個例子:

<body> 
<div> 
<button>點擊</button> 
</div> 
</body> 

// 冒泡型事件模型: button->div->body (IE事件流) 
// 捕獲型事件模型: body->div->button (Netscape事件流) 
// DOM事件模型: body->div->button->button->div->body (先捕獲後冒泡) 
複製代碼
  • 參數方面看,低版本的ie沒有回調函數,只能進行冒泡;
  • 從第一個參數是否加"on"問題看,低版本IE不支持addEventListener(),支持attachEvent,第一個參數須要加on
  • 從this的指向問題看IE指向windows,不指向觸發的函數;

32. javascript是一種什麼樣的語言

  • 解釋性腳本語言,代碼不能進行預編譯;
  • 主要用來向html頁面添加交互行爲;
  • 能夠直接嵌入到html頁面,或單獨寫成js文件。建議單獨寫成文件,有利於結構和行爲分離,利於維護;
  • 跨平臺性,在絕大多數瀏覽器支持下,能夠在多種平臺下運行,例如windowslinux等;

33. DOM和BOM是什麼

首先咱們須要知道:javascript是由ECMAScript,DOM,BOM三部分構成的

  • ECMAScript是一種語言,是對規定的語法,操做,關鍵字,語句的一個描述,javascript實現了ECMAScript;
  • DOM是文檔對象模型,包括了獲取元素,修改樣式以及操做元素等三方面的內容,也是一般咱們用的最多的操做,其提供了不少兼容性的寫法;
  • BOM是瀏覽器對象模型,包括瀏覽器的一些操做,window.onload, window.open等還有瀏覽器時間,監聽窗口的改變onresize,監聽滾動事件onscroll等;

34. 如何實現多個標籤之間的通訊

  • 調用 localStorage

(1)、在一個標籤內使用localStoragesetItem(key, value)添加(刪除或修改)內容;

(2)、在另外一個標籤頁面監聽storage事件;

(3)、獲得localStorage存儲的值,便可實現不用頁面之間的通訊。

  • 調用 cookie+setInterval()

(1)、將要傳遞的信息存儲在cookie中,能夠設置定時讀取cookie的信息,便可隨時獲取想要傳遞的信息。

  • 使用 Webworker

(1)、webworker做爲瀏覽器的一個新特性,能夠提供一個額外的線程來執行一些js代碼,而且對瀏覽器用戶界面不影響;

(2)、普通的Webworkernew worker()便可建立,這種webworker是當前頁面專有的。而後還有種共享worker(SharedWorker),這種是能夠多個標籤頁、iframe共同使用;

  • 使用 SharedWorker

(1)、SharedWorker能夠被多個window共同使用,但必須保證這些標籤頁都是同源的(相同的協議,主機和端口號);

35. 哪些操做會形成內存泄露

內存泄露是指一塊被分配的內存既不能使用,又不能回收,直到瀏覽器進程結束。

如下幾點回形成內存泄露:

  • 過量使用閉包會引發內存泄露(解決:將事件處理函數定義在外部,解除閉包,或者在定義事件處理函數的外部函數中,刪除對dom的引用);
  • 控制檯日誌(解決:項目完成後記得刪除多餘的控制檯打印);
  • 循環,也就是兩個對象彼此引用且彼此保留;
  • setTimeout的第一個參數是字符串而不是函數的時候也會形成內存泄露(解決:儘可能不要講第一個參數定義爲字符串);
  • 意外的全局變量也會引發內存泄漏(解決:使用嚴格模式避免)。
  • 沒有清理DOM元素(解決: 手動刪除);

36. js垃圾回收的幾種方式

javascript具備自動垃圾回收機制,垃圾器回收會按照固定的時間間隔週期性的執行。

常見的垃圾回收機制有兩種: 標記清除引用計數

標記清除

原理: 當變量進入環境時,將這個變量標記爲「進入環境」。當變量離開時,則將其標記爲「離開環境」。標記「離開環境」的就回收內存。

工做流程

  • 垃圾回收器,在運行的時候會給存儲在內存中的全部變量都加上標記;
  • 去掉環境中的變量以及被環境中的變量引用的變量的標記;
  • 再被加上標記的會被視爲準備刪除的變量;
  • 垃圾回收器完成內存清除工做,銷燬那些帶標記的值並回收他們所佔用的內存空間;

引用計數

原理: 跟蹤記錄每一個值被引用的次數,聲明一個變量,並將引用 類型賦值給這個變量,則這個值的引用次數+1,當變量的值變成了另外一個,則這個值的引用次數-1,當值的引用次數爲0的時候,就回收。

工做流程

  • 聲明瞭一個變量並將一個引用類型的值賦值給這個變量,這個引用值的引用次數就是1
  • 同一個值又被賦值給另外一個變量,這個引用類型值此時的引用次數+1
  • 當包含這個引用類型值的變量又被賦值成另外一個值,那麼這個引用呢性值的引用次數-1
  • 當引用次數變成0時,說明目前沒法訪問此值;
  • 當垃圾收集器下一次運行時,它會釋放引用次數是0的值所佔的內存;

37. 什麼放在內存中?什麼不放在內存中?

  • 基本類型(Boolean, String, Number, Null, Undefined, Symbol(新增))的值保存在內存中。從一個變量向另外一個變量賦值基本類型的值,會建立這個值的一個副本;
  • 引用數據類型(object)的值是個對象,保存在堆內存中

🌈🌈注意

  • 包含引用類型值的變量實際上包含的並非對象自己,而是一個指向該對象的指針。從一個變量向另外一個變量複製引用類型的值,複製的實際上是指針,所以兩個變量最終指向的都是同一個對象;
  • javascript不容許直接訪問內存中的位置,也就是不能直接訪問操做對象的內存空間。在操做對象時,實際上在操做對象的引用而不是實際的對象;

38. 堆和棧的區別

(1)、堆和棧空間分配的區別

  • 堆(操做系統): 通常由程序員分配釋放,若程序員不釋放,程序結束時可能由OS回收,分配方式相似於鏈表;
  • 棧(操做系統): 由操做系統自動分配釋放,存放函數的參數值,局部變量的值等。其操做方式相似於數據結構中的棧;

(2)、堆和棧緩存方式的區別

  • 堆是存放在二級緩存中的,聲明週期由虛擬機的垃圾回收算法決定(這裏,並非成爲孤兒對象就能被回收)。因此調用這些對象的速度要相對來的低一些;
  • 棧使用的是一級緩存,它們一般都是被調用時處於緩存空間中,調用完畢當即釋放;

(3)、堆和棧結構區別

  • 堆(數據結構):堆能夠被當作是一棵樹,如: 堆排序;
  • 棧(數據結構):是一種先進後出的數據結構;

39. 在瀏覽器中輸入URL到整個頁面顯示在用戶面前時這個過程當中到底發生了什麼(詳解)

(1)、DNS解析

  • 檢查瀏覽器自身的DNS緩存;
  • 若沒有,搜索操做系統自身的DNS緩存;
  • 若沒有,嘗試讀取hosts文件;
  • 若沒有,可向本地配置的首選DNS服務器發起請求;
  • .win系統若沒有好到,能夠操做系統查找NetBIOS name cache或查詢wins服務器或廣播查找或讀取LMHOSTS文件;

(若以上都沒有,則解析失敗)

(2)、TCP三次握手

(3)、瀏覽器向服務器發送http請求

一旦創建了TCP連接,web瀏覽器就會向web服務器發送請求命令。

(4)、瀏覽器發送請求頭信息

瀏覽器發送其請求命令以後,還要以頭信息的形式想web服務器發送一些別的信息,以後瀏覽器發送了一空白行開通知服務器,它已經結束了該頭信息的發送。

(5)、服務器處理請求

服務器收到http請求以後,肯定用相應的一眼來處理請求。讀取參數並進行邏輯操做後,生成指定的數據。

(6)、服務器作出響應

客戶端向服務器發送請求後,服務端向客戶端作出應答。

(7)、服務器發送應答頭信息

正如客戶端會隨同請求發送關於自身的信息同樣,服務器也會隨同應答向用戶發送關於它本身的數據以及被請求的文檔。

(8)、服務器發送數據

web服務器向瀏覽器發送信息後,它會發送一個空白行來表示頭信息的發送到此結束。接着,它會以Content-Type應答頭信息所描述的格式發送用戶所請求的實際數據。

(9)、 TCP關閉(四次揮手)

通常狀況下,一旦web服務器向瀏覽器發送了請求數據,它就要關閉tcp連接。若是瀏覽器或服務器在其頭信息加入了Connection:keep-alive,則會保持長鏈接狀態,也就是TCP連接在發送後仍保持打開狀態,瀏覽器能夠繼續經過仙童的連接發送請求。

(優勢:保持連接節省了爲每一個請求創建新連接所屬的時間,還節約了網絡寬帶 )

40. 繼承的方法有哪些

  • 原型鏈繼承;
  • 構造函數繼承;
  • 實例繼承;
  • 組合繼承;
  • 拷貝繼承;
  • 寄生組合繼承;

🚚...................................................ᴅᴜᴅᴜ!

41. 🥴JavaScript和ASP腳本相比,哪一個更快

通常狀況下,javascript會更快。javascript是一種客戶端語言,所以它不須要web服務器的協助來執行。另外一方面,ASP是服務端語言,所以老是比javascript慢。可是須要注意的是:javascript如今也能夠用於服務端語言(例如nodejs)。

42. Java和JavaScript之間的區別

  • 首先,java是一門十分完整,成熟的編程語言;相比之下,javascript是一個能夠被引入HTML頁面的編程語言。這兩種語言並非徹底相互依賴的,而是真對不一樣的意圖而設計的。
  • 其次,java是一種面向對象編程(OOPS)或結構化的編程語言,相似於C++C;而javascript是客戶端腳本語言,它被稱爲非結構化編程。

43. 什麼是負無窮大

負無窮大是javascript中的一個數字,能夠經過將負數除以零獲得。

44. 什麼是未聲明和未定義的變量

  • 未聲明的變量是指程序中不存在且爲聲明的變量。若是程序嘗試讀取爲聲明的變量的值,運行會報錯;
conosle.log(b);

// Uncaught ReferenceError: conosle is not defined
    at <anonymous>:1:1
複製代碼
  • 未定義的變量是在程序中聲明可是還沒有賦予任何值的變量。若是程序中使用了未定義的變量的值,會返回一個undefined
let c;
console.log(c);  // undefined
複製代碼

45. javascript中有幾種定時器以及其如何工做

定時器用於在設定的時間執行一段代碼,或者在給定的時間間隔內重複該代碼。經過函數setTimeoutsetIntervalclearInterval來完成。

  • setTimeoutfunctiondelay)函數用於移動在所述延遲以後調用特定功能的定時器;
  • setIntervalfunctiondelay)函數用於在提到的延遲中重複執行給定的功能,只有在取消時才能中止;
  • clearIntervalid)函數指示定時器中止;

🌈🌈注意: 定時器在一個線程內運行,所以事件可能須要排隊等待執行;

46. ViewState和SessionState有什麼區別

  • ViewState:特定於會話中的頁面;
  • SessionState: 特定於可在web應用程序中的全部頁面上訪問的用戶特定數據;

47. delete操做符的功能是什麼

delete操做符用於刪除程序中的全部變量或對象,可是不能刪除使用var關鍵字聲明的變量。

48. 5 + 8 + '7' 和 5 + '8' + 7 的結果是啥

console.log(5 + 8 + '7');  // 137
console.log(5 + '8' + 7);  // 587
複製代碼

能夠這樣理解:連續的整數能夠直接相加,字符串直接相連。

49. 在JavaScript中使用innerHTML的缺點是什麼

  • 內容隨處可見;
  • 不能像‘追加到innerHTML’同樣使用;
  • 即便使用+=like "innerHTML = innerHTML + 'html'",舊的內容仍然會被html替換;
  • 整個innerHTML內容被從新解析並構建成元素,所以它的速度會慢不少;
  • innerHTML不提供驗證,所以可能會在文檔中插入有效的和破壞性的HTML並將其中斷;

50. JavaScript中不一樣類型的錯誤有幾種

JS的錯誤類型通常包含六種常見的派生錯誤以及手動拋出錯誤類型。

(1)、常見的幾種錯誤類型

  • SyntaxError: 語法錯誤,通常指解析代碼時發生的語法錯誤;
  • ReferenceError:引用錯誤,通常指引用一個不存在的變量時發生的錯誤。
  • TypeError: 類型錯誤,通常是變量或參數不是預期類型時發生錯誤。
  • EvalError eval(): 函數執行錯誤,通常指當eval()函數沒有被正確執行時,會拋出evalError錯誤;
  • RangeError: 範圍錯誤,通常指當一個值超出有效範圍時發生的錯誤。

🚚...................................................ᴅᴜᴅᴜ!

51. 🥱延遲腳本在JavaScript中的做用

通常狀況下,當頁面首先加載腳本時,加載期間頁面的HTML代碼將會暫停解析,直到腳本加載完才能執行。

因此會出現這麼一種狀況,就是當服務器速度很慢或者腳本很沉重的狀況下,會致使網頁延遲。在使用Defer時,腳本會延遲執行直到html解析器運行完成。這極大程度上減小了加載時間,提高了顯示速度。

52. decodeURI()和encodeURI()是什麼

encodeURI()用於將URL轉爲十六進制編碼,而decodeURI()用於將編碼的URL轉換成正常的URL

53. hash(哈希)表是什麼

哈希表(亦稱散列表),是根據關鍵碼值直接進行訪問的數據結構。也就是說,它經過把關鍵碼映射到表中一個位置來訪問記錄,以加快查找的速度。這個映射函數也稱散列函數,存放記錄的數組叫作散列表。

54. 節點有幾種類型(三種)

  • 元素節點: nodeType === 1;
  • 屬性節點: nodeType === 2
  • 文本節點: nodeType === 3

55. innerHTML和outerHTML的區別

  • innerHTML(元素內包含的內容);
  • outerHTML(本身以及元素內的內容);

56. offsetWidth offsetHeight和clientWidth clientHeight間的區別

  • offsetWidth/offsetHeightcontent寬/高 + padding寬/高 + border寬/高);
  • clientWidth/clientHeight (content寬/高 + padding寬/高);

57. 幾種減低頁面加載時間的方法

  • 壓縮CSSJS文件;
  • 合併CSSJS文件,減小http請求;
  • 外部JSCSS放在最底層;
  • 減小DOM操做,儘量使用變量代替沒必要要的DOM操做;
  • 優化圖片文件,減少其尺寸,特別是縮略圖;
  • 使用多域名負載網頁內的多個文件、圖片;
  • 服務器開啓gzip壓縮;

58. 描述AJAX的工做原理

  • 第一步: 建立AJAX對象(XMLHttpRequest/ActiveXObject(Microsoft.XMLHttp));
  • 第二步: 使用open打開鏈接,格式爲open(請求方式,'請求路徑',同步/異步);
  • 第三步: 發送send();
  • 第四步:當ajax對象完成第四步(onreadystatechange),數據接收完成。再判斷對象狀態碼(readystate) 當狀態碼爲成功接收的狀態碼時,HTTP響應徹底接收 。 再判斷http響應狀態(200-300之間或者304),(緩存)執行回調函數 獲取的數據轉成字符串格式(responseText)

缺點

  • 對搜索引擎不友好;
  • 跨域問題的限制;
  • 要實現ajax下的先後退功能成本比較大;

59. http的cache機制,以及200狀態下如何實現 from cache

含義

瀏覽器緩存(Browser Caching)是爲了加速瀏覽,瀏覽器在用戶磁盤上歲最近請求過的文檔進行存儲,當用戶再次訪問這個文檔時,瀏覽器會從本地磁盤顯示此文檔,從而提高頁面加載速率。

cache的做用

  • 減小延遲,讓網站的運行速度更快,帶來更好的用戶體驗;
  • 避免網絡擁塞,減小請求量,減小輸出帶寬;

實現手段

cache-control中的max-age是實現內容cache的重要手段,經常使用的策略有如下三種:

  • max-ageETag的組合;
  • max-age
  • max-ageLast-Modified(If-Modified-Since)的組合;

拓展

在此,拓展一下有關強制緩存(200)和協商緩存(304)部分的內容。

  • 強制緩存(也稱強緩存),指當瀏覽器去請求某個文件的時候,服務端就在respone header裏面對該文件作了緩存配置。強制緩存不會向服務器發送請求,直接從緩存中讀取資源,在chrome控制檯的network選項中能夠看到該請求返回200的狀態碼;
  • 協商緩存:強制緩存給資源設置了過時時間,在未過時時,能夠說是給用戶自給自足用的。可是當資源過時時,就須要去請求服務器,這時候請求服務器的過程就能夠設置成協商緩存。協商緩存就是須要客戶端和服務端進行交互的。協商緩存將緩存信息中的EtagLast-Modified經過請求發給服務器,由服務器校驗,返回狀態碼304時,瀏覽器就能夠直接使用緩存。

共同點: 都是從客戶端中讀取數據;

區別: 強緩存不會發出請求,協商緩存會發出請求。

緩存中header(頭部)的參數:

(1)、強制緩存:

  • Expires(經常使用):response header裏的過時時間,瀏覽器再次加載資源時,若是在這個過時時間內,則命中強緩存。
  • Cache-Control(經常使用):當值設爲max-age=120時,則表明在這個請求正確返回時間(瀏覽器也會記錄下來)的2分鐘內再次加載資源,就會命中強緩存。
  • no-cache:不使用本地緩存。須要使用緩存協商,來驗證是否過時;
  • no-store:不可緩存;
  • public:客戶端和代理服務器均可緩存;
  • private:只能有客戶端緩存;

(2)、協商緩存

  • Etag:即文件hash,每一個文件惟一。web服務器響應請求時,告訴瀏覽器當前資源在服務器的惟一標識(生成規則由服務器決定);
  • If-None-Match:當資源過時時(使用Cache-Control標識的max-age),發現資源具備Etag聲明,則再次向web服務器請求時帶上頭If-None-Match (Etag的值)。web服務器收到請求後發現有頭If-None-Match 則與被請求資源的相應校驗串進行比對,決定是否命中協商緩存;
  • Last-Modify/If-Modify-Since:文件的修改時間,精確到秒。瀏覽器第一次請求一個資源的時候,服務器返回的header中會加上Last-ModifyLast-modify是一個時間標識該資源的最後修改時間;當瀏覽器再次請求該資源時,request的請求頭中會包含If-Modify-Since,該值爲緩存以前返回的Last-Modify。服務器收到If-Modify-Since後,根據資源的最後修改時間判斷是否命中緩存;

🌈🌈注意

  • Etag要優於Last-Modified
  • 在優先級上,服務器校驗優先考慮Etag
  • 在性能上,Etag要遜於Last-Modified

60. 什麼是虛擬DOM,爲何要使用以及和真實DOM的區別

含義及使用

這裏,小編的理解是:虛擬DOM是真實DOM的內存表示,是一種編程概念,一種模式。它的做用是判斷DOM是否改變、哪些部分須要被從新渲染。這樣,不須要操縱真實的DOM,同時極大的提升了React的性能。

虛擬DOM使用diff算法,當咱們屢次修改某一部分的內容時,首先在虛擬DOM樹從上至下進行同層比對(不影響真實DOM),上層發生變化,下層從新渲染,直到最後修改完成,再在真實DOM中渲染。

使用虛擬DOM的緣由是,能夠極大程度上減小DOM節點的迴流和重繪問題,節約資源,提高運行效率。

區別

  • 虛擬DOM不會進行重排和重繪;
  • 虛擬DOM進行頻繁的修改,而後一次性比較並修改真實DOM中須要修改的部分,最後進行迴流和重繪,有效的減小了過多DOM節點回流和重繪資源消耗的問題;
  • 虛擬DOM有效下降大面積(真實DOM節點)的迴流和重繪,由於最終與真實DOM比較差別,能夠局部渲染。

🚚...................................................ᴅᴜᴅᴜ!

61. 🤫跨域以及解決辦法

協議、域名、端口號不一樣--跨域(也能夠理解爲協議、域名、端口號相同--同源策略)

解決跨域的幾種辦法

  • document.domain + iframe(只有在主域相同的狀況下才能使用);
  • 動態建立script
  • location.hash + iframe;
  • window.name + iframe;
  • postMessageHTML5中的XMLHttpRequest Level 2中的API);
  • CORS(跨域資源共享);
  • jsonp;
  • websockets;

62. 常談的CSRF和XSS

XSS(Cross Site Scripting)

跨站腳本攻擊,黑客將惡意腳本代碼植入到頁面中從而實現盜取用戶信息等操做(注意這裏操做的是用戶,攻擊的方式只是代碼的嵌入)。

預防措施

  • 對輸入,輸出的結果進行必要的轉義;
  • 儘可能使用post,對get使用時儘可能對路徑長度作限制;
  • 使用httponly來方式黑客經過腳本獲取用戶cookie數據。
  • 於客戶自己,養成良好習慣,提升警戒,不隨意點來陌生連接;

CSRF(cross-site request forgery)

跨站請求僞造,黑客假裝成用戶身份來執行一些非用戶自願的惡意以及非法操做(注意,這裏是黑客假裝成用戶操做)。

預防措施

  • 運用驗證碼;
  • 使用token id令牌;
  • 判斷請求的reFerer是否正確;

區別

  • CSRF須要登錄後操做,XSS不須要;
  • CSRF是請求頁面api來實現非法操做,XSS是向當前頁面植入js腳原本修改頁面內容。

63. 如何看待AMD和CommonJS

瀏覽器端異步和服務器端同步的模塊化編程規範。

CommonJS:是爲了解決 JavaScript 的做用域問題而定義的模塊形式,可使每一個模塊它自身的命名空間中執行。該規範的主要內容是,模塊必須經過 module.exports 導出對外的變量或接口,經過 require() 來導入其餘模塊的輸出到當前模塊做用域中,module標識模塊自己。

AMD:是全局定義的,當即執行函數提供 moduleexports 兩個外部變量,模塊就放在這個當即執行函數裏面。模塊的輸出值放在 module.exports 之中,這樣就實現了模塊的加載。

64. 有幾種匿名函數(沒有定義函數名的函數)用例

  • 定義回調函數;
  • 當即執行函數;
  • 做爲返回值的函數;
  • 使用方法爲 var func = function() {};定義的函數;

65. null,undefined 或 undeclared的區別以及如何檢測

區別

  • null: 未定義的屬性;
  • undefined: 定義可是爲賦值的爲undefined
  • undecleared: javascript訪問不會報錯;

檢測方式

  • null是一種特殊的object,表示無值;
console.log(typeof null);  // object

const a = null;
if(!a && typeof(a) !== 'undefined' && a!==0) {
    alert('a is null')
} else {
     alert('a is not null')
}
複製代碼
  • undefined: 是聲明但未賦值的變量;
const a = undefined;
if(typeof(a) === 'undefined') {
    alert('a is undefined')
} else {
     alert('a is not undefined')
}
複製代碼
  • undeclaredundeclared 是未聲明也未賦值的變量,JavaScript訪問會報錯。

67. 可變 (mutable) 和不變 (immutable) 對象的區別

  • 可變(mutable): 在JS中,對象是引用類型的數據,其優勢在於頻繁的修改對象時都是在原對象的基礎上修改的,並不須要進行從新建立,這樣就能夠有效的利用內存,不會形成內存空間的浪費;
  • 不可變(immutable): 每一次修改一個immutable對象時,都會建立一個新的不可變對象,在新對象上的操做不會影響到原對象的數據。

68. 使用 Promises 而非回調 (callbacks) 優缺點是什麼

Promise是異步編程的一種解決方案,比傳統的解決方案 回調函數和事件 更合理和更強大。它由社區最先提出和實現,ES6將其寫進了語言標準,統一了用法,原生提供了Promise對象。

所謂Promise,簡單說就是一個容器,裏面保存着某個將來纔會結束的事件(一般是一個異步操做)的結果。從語法上說,Promise是一個對象,從它能夠獲取異步操做的消息。Promise提供統一的API,各類異步操做均可以用一樣的方法進行處理。

有了Promise對象,就能夠將異步操做以同步操做的流程表達出來,避免了層層嵌套的回調函數。此外,Promise對象提供統一的接口,使得控制異步操做更加容易。

Promise同時存在一些缺點,例如:

  • 第一: 沒法取消Promise,一旦新建它就會當即執行,沒法中途取消;
  • 第二:若是不設置回調函數,Promise內部拋出的錯誤,不會反應到外部;
  • 第三:當處於Pending狀態時,沒法得知目前進展到哪個階段(剛剛開始仍是即將完成)。

69. 瀏覽器特性檢測,特性推斷和瀏覽器 UA 字符串嗅探的區別

  • 特性檢查更適合針對實現了特定特性的瀏覽器進行操做。
  • UA字符串因爲被瀏覽器廠商能夠隨意修改,所以給使用者的感受不太靠譜。

70. 理解 Function.prototype.bind

Function.prototype.bind方法會建立一個新的函數,當這個新函數被調用時,它的this值是傳給bind()的第一個參數,它的參數是bind()的其它參數和其本來的參數。

71. 持續更新ing🍀🍀

⏳⏳ ......

寫在最後

關於javascript部分的整理,就先整理到這裏吧,後繼會持續更新。有關開發性能優化篇小編還在整理當中,可是因爲最近項目壓身,可能會延遲一丟丟吧(生活不易且珍惜🌻🌻)。

整理的過程當中,不免會有疏漏,如果看到有誤或者須要補充的知識點,歡迎留言小編💌💌。

相關文章
相關標籤/搜索