前端技術面——(js基礎一)

Yolanda_Lu發表於2018-09-27

1、Vue雙向資料繫結是如何實現的?原文

  • vue.js 是採用資料劫持結合釋出者-訂閱者模式的方式,通過Object.defineProperty()來劫持各個屬性的setter,getter,在資料變動時釋出訊息給訂閱者,觸發相應的監聽回撥
  1. Vue.js 最核心的功能有兩個,一是響應式的資料繫結系統,二是元件系統。
  2. 訪問器屬性是物件中的一種特殊屬性,它不能直接在物件中設定,而必須通過 defineProperty() 方法單獨定義。
  3. 訪問器屬性的"值"比較特殊,讀取或設定訪問器屬性的值,實際上是呼叫其內部特性:get和set函式。
  4. get 和 set 方法內部的 this 都指向 obj,這意味著 get 和 set
    函式可以操作物件內部的值。另外,訪問器屬性的會"覆蓋"同名的普通屬性,因為訪問器屬性會被優先訪問,與其同名的普通屬性則會被忽略。

Angularjs和Vue.js對比

前端技術面——(js基礎一)

2、極簡雙向資料繫結是如何實現的?

前端技術面——(js基礎一)

3、原型和原型鏈是什麼?原文

1、建構函式建立物件 我們先使用建構函式建立一個物件:

前端技術面——(js基礎一)

2、 prototype 每個函式都有一個prototype屬性,函式的prototype屬性指向了一個物件,這個物件正是呼叫該建構函式而建立的例項的原型,也就是這個例子中的person1和person2的原型。每一個JavaScript物件(null除外)在建立的時候就會與之關聯另一個物件,這個物件就是我們所說的原型,每一個物件都會從原型”繼承”屬性。

3、proto 這是每一個JavaScript物件(除了null)都具有的一個屬性,叫__proto__,這個屬性會指向該物件的原型。

4、construcotr,每個原型都有一個constructor屬性指向關聯的建構函式

5、例項與原型 當讀取例項的屬性時,如果找不到,就會查詢與物件關聯的原型中的屬性,如果還查不到,就去找原型的原型,一直找到最頂層為止。

前端技術面——(js基礎一)

6、原型鏈 那Object.prototype的原型呢? null,嗯,就是null,所以查到Object.prototype就可以停止查詢了

前端技術面——(js基礎一)

4、總結ES6常用的新特性。 原文

在這裡列舉幾個常用的:

  • 箭頭函式
  • Promise
  • Let與Const
  • 模組化
  • 函式引數預設值
  • 模板字串
  • 解構賦值
  • 延展操作符
  • 物件屬性簡寫

5、箭頭函式。 原文

箭頭函式被呼叫的時候,不會自動繫結一個this物件。換句話說,箭頭函式根本就沒有自己的this。它的this都是捕獲自其所在上下文的this值。
  • 作為匿名函式被呼叫。

前端技術面——(js基礎一)

  • 作為方法被呼叫

前端技術面——(js基礎一)

  • 在方法內部被呼叫

前端技術面——(js基礎一)

  • 使用new 操作符呼叫,會丟擲錯誤
    前端技術面——(js基礎一)
  • 使用call和apply,bind()呼叫

前端技術面——(js基礎一)

總結一下
箭頭函式沒有自己的this物件,它總是搬運外部環境的this物件。因此,只要離它最近的外部環境中的this改變,箭頭函式中的this就改變。如果離它最近的環境中的this,沒有改變。那麼箭頭函式中的this就不會改變。

原文

6.promise是什麼? 原文

什麼是Prmoise

Promise物件可以理解為一次執行的非同步操作,使用promise物件之後可以使用一種鏈式呼叫的方式來組織程式碼

Promise物件的特點:

1、物件的狀態不受外界影響。
Promise物件代表一個非同步操作,有三種狀態:
pending(執行中)
Resolved(成功,又稱Fulfilled)
rejected(拒絕)
2、一旦狀態改變,就不會再變,任何時候都可以得到這個結果。
Promise物件的狀態改變,只有兩種可能:從Pending變為Resolved和從Pending變為Rejected

Promise物件的缺點:

1、無法取消Promise,一旦新建它就會立即執行,無法中途取消。
2、如果不設定回撥函式,Promise內部丟擲的錯誤,不會反應到外部。
3、當處於Pending狀態時,無法得知目前進展到哪一個階段(剛剛開始還是即將完成)。

promise相容性

除了IE這種古老的瀏覽器和一些低版本的安卓外,現代瀏覽器支援還是挺好的

Promise的使用

1、基本用法:
(1)、首先我們new一個Promise,將Promise例項化
(2)、然後在例項化的promise可以傳兩個引數,一個是成功之後的resolve,一個是失敗之後的reject
(3)、Promise例項生成以後,可以用then方法分別指定Resolved狀態和Reject狀態的回撥函式

2、鏈式操作
也許你會說,Promise只是簡化層層回撥的寫法而已吧,其實不然,它的精髓是通過維護狀態、傳遞狀態的方式來使回撥方式能夠及時的呼叫,因此,相比於callback,它更靈活,更簡單。

promise.all方法

Promise.all 可以接收一個元素為 Promise 物件的陣列作為引數,當這個陣列裡面所有的 Promise 物件都變為 resolve 時,該方法才會返回。
all接收一個陣列作為引數,p1,p2是並行執行的,等兩個都執行完了,才會進入到then,all會把所有的結果放到一個陣列中返回,所以我們列印出我們的結果為一個陣列。

promise.race方法

race只返回跑的快的值,也就是說result返回比較快執行的那個。

前端技術面——(js基礎一)
前端技術面——(js基礎一)

前端技術面——(js基礎一)

7、JS中事件冒泡與捕獲。 原文

1、document 往 target節點,捕獲前進,遇到註冊的捕獲事件立即觸發執行
2、到達target節點,觸發事件(對於target節點上,是先捕獲還是先冒泡則捕獲事件和冒泡事件的註冊順序,先註冊先執行)
3、target節點 往 document 方向,冒泡前進,遇到註冊的冒泡事件立即觸發
總結下就是:
對於非target節點則先執行捕獲在執行冒泡
對於target節點則是先執行先註冊的事件,無論冒泡還是捕獲

8、http和https

(1)http和https的基本概念

http: 超文字傳輸協議,是一個客戶端和伺服器端請求和應答的標準(TCP),用於從WWW伺服器傳輸超文字到本地瀏覽器的傳輸協議。
https: 是以安全為目標的HTTP通道,簡單講是HTTP的安全版,即HTTP下加入SSL層。
https協議的主要作用是:建立一個資訊保安通道,來確保陣列的傳輸,確保網站的真實性。

(2)http和https的區別?

https協議是由http和ssl協議構建的可進行加密傳輸和身份認證的網路協議,比http協議的安全性更高。

1.Https協議需要ca證照,費用較高。
2.http是超文字傳輸協議,資訊是明文傳輸,https則是具有安全性的ssl加密傳輸協議。
3.使用不同的連結方式,埠也不同,一般而言,http協議的埠為80,https的埠為443
4.http的連線很簡單,是無狀態的;HTTPS協議是由SSL+HTTP協議構建的可進行加密傳輸、身份認證的網路協議,比http協議安全。

(3)https協議的工作原理

客戶端在使用HTTPS方式與Web伺服器通訊時有以下幾個步驟。

1.客戶使用https url訪問伺服器,則要求web 伺服器建立ssl連結。
2.web伺服器接收到客戶端的請求之後,會將網站的證照(證照中包含了公鑰),返回或者說傳輸給客戶端。
3.客戶端和web伺服器端開始協商SSL連結的安全等級,也就是加密等級。
4.客戶端瀏覽器通過雙方協商一致的安全等級,建立會話金鑰,然後通過網站的公鑰來加密會話金鑰,並傳送給網站。
5.web伺服器通過自己的私鑰解密出會話金鑰。
6.web伺服器通過會話金鑰加密與客戶端之間的通訊。

9.tcp三次握手,一句話概括

三次握手可以簡化為:C發起請求連線S確認,也發起連線C確認我們再看看每次握手的作用:

前端技術面——(js基礎一)
第一次握手:S只可以確認 自己可以接受C傳送的報文段
第二次握手:C可以確認 S收到了自己傳送的報文段,並且可以確認 自己可以接受S傳送的報文段
第三次握手:S可以確認 C收到了自己傳送的報文段

10.TCP和UDP的區別

  1. TCP是面向連線的,udp是無連線的即傳送資料前不需要先建立連結。
  2. TCP提供可靠的服務。也就是說,通過TCP連線傳送的資料,無差錯,不丟失,不重複,且按序到達;UDP盡最大努力交付,即不保證可靠交付。 並且因為tcp可靠,面向連線,不會丟失資料因此適合大資料量的交換。
  3. TCP是面向位元組流,UDP面向報文,並且網路出現擁塞不會使得傳送速率降低(因此會出現丟包,對實時的應用比如IP電話和視訊會議等)。
  4. TCP只能是1對1的,UDP支援1對1,1對多。
  5. TCP的首部較大為20位元組,而UDP只有8位元組。
  6. TCP是面向連線的可靠性傳輸,而UDP是不可靠的。

11.Cookie、sessionStorage、localStorage的區別

共同點:都是儲存在瀏覽器端,並且是同源的

Cookie:cookie資料始終在同源的http請求中攜帶(即使不需要),即cookie在瀏覽器和伺服器間來回傳遞。而sessionStorage和localStorage不會自動把資料發給伺服器,僅在本地儲存。cookie資料還有路徑(path)的概念,可以限制cookie只屬於某個路徑下,儲存的大小很小隻有4K左右。 (key:可以在瀏覽器和伺服器端來回傳遞,儲存容量小,只有大約4K左右)

sessionStorage:僅在當前瀏覽器視窗關閉前有效,自然也就不可能持久保持,localStorage:始終有效,視窗或瀏覽器關閉也一直儲存,因此用作持久資料;cookie只在設定的cookie過期時間之前一直有效,即使視窗或瀏覽器關閉。(key:本身就是一個回話過程,關閉瀏覽器後消失,session為一個回話,當頁面不同即使是同一頁面開啟兩次,也被視為同一次回話)

localStorage:localStorage 在所有同源視窗中都是共享的;cookie也是在所有同源視窗中都是共享的。(key:同源視窗都會共享,並且不會失效,不管視窗或者瀏覽器關閉與否都會始終生效)

12.自己實現一個bind函式

原理:通過apply或者call方法來實現。

前端技術面——(js基礎一)

13、preventDefault 和 stopPropagation

event.stopPropagation() 方法阻止事件冒泡到父元素,阻止任何父事件處理程式被執行。 preventDefault阻止元素髮生的預設行為。

例如: 當點選提交按鈕時阻止對錶單的提交
阻止一下URL的連結

## 14、寫一個通用事件偵聽函式

前端技術面——(js基礎一)

15、為什麼要用閉包

閉包就是能夠讀取其他函式內部變數的函式
閉包的作用在於,可以通過閉包,設計私有變數及方法。

閉包的三大特點為:

1、函式巢狀函式
2、內部函式可以訪問外部函式的變數
3、引數和變數不會被回收。

16、call和apply和bind有什麼不一樣?

相同點

都是實現繼承或者轉換物件指標的作用
1、call和apply可以改變this的指向
2、第一個引數都是this要指向的物件
3、都可以利用後續引數繼續傳參

不同點

1、call和apply是對函式的直接呼叫,而bind方法返回的是一個函式,bind後函式不會立即執行,而是返回了一個改變上下文的函式副本
2、call和apply都可以傳遞引數

什麼是bind

bind()會建立一個新函式,當這個新函式被呼叫時,bind()的第一個引數將作為執行時的this,之後的一序列引數將會在傳遞的實參前作為傳遞的引數

17、前端效能優化你瞭解哪些

內容層面

  • 使用CDN
  • 單域名、多域名,單域名可以減少DNS查詢次數,多域名可以增加瀏覽器並行下載數量,這需要權衡,一般同一個域下不要超過四個資源。
  • 避免重定向(分場景)
  • 避免404

網路層面

  • 利用快取,可以參考另一篇文章手寫檔案伺服器,說說前後端互動
  • 檔案壓縮(通過響應頭Accept-Encoding: gzip, deflate, br告訴伺服器你支援的壓縮型別)
  • 按需載入,提取公共程式碼,tree-shaking等(都可以通過webpack來實現)
  • 減少cookie大小
  • 檔案合併,通過css雪碧圖合併圖片
  • 檔案預載入、圖片懶載入

渲染層間

  • js放底部,css放頂部
  • 減少reflow(迴流)和repaint(重繪)
  • 減少dom節點

程式碼層面

  • 快取dom節點,減少節點查詢,css選擇器層級優化
  • 減少dom節點操作
  • 合理使用break、continue、return等,優化迴圈
  • 像react用到的事件委託、物件池等手段

18、說說瀏覽器的reflow和repaint

瀏覽器解析過程

解析html生成dom樹
解析css
把css應用於dom樹,生成render樹(這裡記錄這每一個節點和它的樣式和所在的位置)
把render樹渲染到頁面

reflow(迴流)

reflow翻譯為迴流,指的是頁面再次構建render樹。每個頁面至少發生一次迴流,就是第一次載入頁面的時候 此外,當頁面中有任何改變可能造成文件結構發生改變(即元素間的相對或絕對位置改變),都會發生reflow,常見的有:

新增或刪除元素(opacity:0除外,它不是刪除)
改變某個元素的尺寸或位置
瀏覽器視窗改變(resize事件觸發)

repaint(重繪)

repaint翻譯為重繪,它可以類比為上面的第四步,根據render樹繪製頁面,它的效能損耗比迴流要小。每次迴流一定會發生重繪。此外,以下操作(不影響文件結構的操作,影響結構的會發生迴流)也會發生重繪:

元素的顏色、透明度改變
text-align等

19、深拷貝

function deepcopy(obj) {
        let res = {};
        for (key in obj) {
            if (typeof obj[key] == 'object') {
                res[key] = deepcopy(obj[key]);
            } else {
                res[key] = obj[key];
            }
        }
        return res;
    }
複製程式碼

20、defer和async的區別 原文

定義

defer:此布林屬性被設定為向瀏覽器指示指令碼在文件被解析後執行。
async:設定此布林屬性,以指示瀏覽器如果可能的話,應非同步執行指令碼。
1. 對於defer,我們可以認為是將外鏈的js放在了頁面底部。js的載入不會阻塞頁面的渲染和資源的載入。不過defer會按照原本的js的順序執行,所以如果前後有依賴關係的js可以放心使用。
2. 對於async,這個是html5中新增的屬性,它的作用是能夠非同步的載入和執行指令碼,不因為載入指令碼而阻塞頁面的載入。一旦載入到就會立刻執行在有async的情況下,js一旦下載好了就會執行,所以很有可能不是按照原本的順序來執行的。如果js前後有依賴性,用async,就很有可能出錯。

區別

相同點:

1. 載入檔案時不阻塞頁面渲染
2. 對於inline的script(內聯指令碼)無效
3. 使用這兩個屬性的指令碼中不能呼叫document.write方法
4. 有指令碼的onload的事件回撥

不同點:

1. html的版本html4.0中定義了defer;html5.0中定義了async
2. 瀏覽器相容性
3. 執行時刻每一個async屬性的指令碼都在它下載結束之後立刻執行,同時會在window的load事件之前執行。所以就有可能出現指令碼執行順序被打亂的情況;每一個defer屬性的指令碼都是在頁面解析完畢之後,按照原本的順序執行,同時會在document的DOMContentLoaded之前執行。

結語

1. 如果async為true,那麼指令碼在下載完成後非同步執行。
2. 如果async為false,defer為true,那麼指令碼會在頁面解析完畢之後執行。
3. 如果async和defer都為false,那麼指令碼會在頁面解析中,停止頁面解析,立刻下載並且執行。

最後給一點個人的建議,無論使用defer還是async屬性,都需要首先將頁面中的js檔案進行整理,哪些檔案之間有依賴性,哪些檔案可以延遲載入等等,做好js程式碼的合併和拆分,然後再根據頁面需要使用這兩個屬性。

21、詳解toString

toString() 方法返回一個表示該物件的字串。 valueOf() 方法返回指定物件的原始值。

前端技術面——(js基礎一)

前端技術面——(js基礎一)

前端技術面——(js基礎一)

22、如何去除字串首位空格?

//es6
' ab '.trim()      //"ab" 
//正則
' ab '.replace(/^\s*|\s*$/g,'')  //"ab"
複製程式碼

23、jsonp原理?缺點?

工作原理:使用script標籤實現跨域訪問,可在url中指定回撥函式,獲取JSON資料並在指定的回撥函式中執行jquery實現jsop。
缺點:只支援GET方式的jsonp實現,是一種指令碼注入行為存在一定的安全隱患。如果返回的資料格式有問題或者返回失敗了,並不會報錯。

24、設計模式

1、工廠模式
 function People() {
    var obj = new Object();
    obj.name = '小明';
    obj.age = 12;
    obj.say = function() {
        // alert(this.name);
        return this.name;
    }
    return obj;
}

2、建構函式模式
function People() {
    this.name = '小明';
    this.say = function() {
        return this.name;
    }
}

3、原型模式
function People(name) {
    this.name = name;
}
People.prototype.sayName = function() {
    console.log(this.name);
}
複製程式碼

25、繼承

1、原型鏈繼承
function People(name) {
    this.name = name;
}
People.prototype.sayName = function() {
    console.log(this.name);
}
function Student(name, grade) {
    this.name = name;
    this.grade = grade;
    this.sayGrade = function() {
        console.log(this.grade);
    }
}
Student.prototype = new People();


2、建構函式繼承
function People() {
    this.name = name;
}
People.prototype.sayName = function() {
    console.log(this.name);
}
People.prototype.type = function() {
    console.log('人');
};
function Student(name, grade) {
    this.name = name;
    this.grade = grade;
    People.apply(this);
}
var student = new Student('小蘭', 5);
student.type();
複製程式碼

26、HTTP的幾種請求方法用途

1、GET方法

傳送一個請求來取得伺服器上的某一資源

2、POST方法

向URL指定的資源提交資料或附加新的資料

3、PUT方法

跟POST方法很像,也是想伺服器提交資料。但是,它們之間有不同。PUT指定了資源在伺服器上的位置,而POST沒有

4、HEAD方法

只請求頁面的首部

5、DELETE方法

刪除伺服器上的某資源

6、OPTIONS方法

它用於獲取當前URL所支援的方法。如果請求成功,會有一個Allow的頭包含類似“GET,POST”這樣的資訊
瀏覽器必須首先使用 OPTIONS 方法發起一個預檢請求(preflight request),從而獲知服務端是否允許該跨域請求。伺服器確認允許之後,才發起實際的 HTTP 請求。

7、TRACE方法

TRACE方法被用於激發一個遠端的,應用層的請求訊息迴路

8、CONNECT方法

把請求連線轉換到透明的TCP/IP通道

27、從瀏覽器位址列輸入url到顯示頁面的步驟

  • 瀏覽器根據請求的URL交給DNS域名解析,找到真實IP,向伺服器發起請求;連結
  • 伺服器交給後臺處理完成後返回資料,瀏覽器接收檔案(HTML、JS、CSS、圖象等);
  • 瀏覽器對載入到的資源(HTML、JS、CSS等)進行語法解析,建立相應的內部資料結構(如HTML的DOM);
  • 載入解析到的資原始檔,渲染頁面,完成。

28、如何進行網站效能優化

1. content方面

  • 減少HTTP請求:合併檔案、CSS精靈、inline Image

  • 減少DNS查詢:DNS快取、將資源分佈到恰當數量的主機名

  • 減少DOM元素數量

2. Server方面

  • 使用CDN

  • 配置ETag

  • 對元件使用Gzip壓縮

3. Cookie方面

  • 減小cookie大小

4. css方面

  • 將樣式表放到頁面頂部
  • 不使用CSS表示式
  • 使用不使用@import

5. Javascript方面

  • 將指令碼放到頁面底部

  • 將javascript和css從外部引入

  • 壓縮javascript和css

  • 刪除不需要的指令碼

  • 減少DOM訪問

6. 圖片方面

  • 優化圖片:根據實際顏色需要選擇色深、壓縮
  • 優化css精靈
  • 不要在HTML中拉伸圖片

29、HTTP狀態碼及其含義

1XX:資訊狀態碼

100 Continue 繼續,一般在傳送post請求時,已傳送了http header之後服務端將返回此資訊,表示確認,之後傳送具體引數資訊

2XX:成功狀態碼

200 OK 正常返回資訊

201 Created 請求成功並且伺服器建立了新的資源

202 Accepted 伺服器已接受請求,但尚未處理

3XX:重定向

301 Moved Permanently 請求的網頁已永久移動到新位置。

302 Found 臨時性重定向。

303 See Other 臨時性重定向,且總是使用 GET 請求新的 URI。

304 Not Modified 自從上次請求後,請求的網頁未修改過。

4XX:客戶端錯誤

400 Bad Request 伺服器無法理解請求的格式,客戶端不應當嘗試再次使用相同的內容發起請求。

401 Unauthorized 請求未授權。

403 Forbidden 禁止訪問。

404 Not Found 找不到如何與 URI 相匹配的資源。

5XX: 伺服器錯誤

500 Internal Server Error 最常見的伺服器端錯誤。

503 Service Unavailable 伺服器端暫時無法處理請求(可能是過載或維護)。

31、介紹js有哪些內建物件?

  • Object 是 JavaScript 中所有物件的父物件

  • 資料封裝類物件:Object、Array、Boolean、Number 和 String

  • 其他物件:Function、Arguments、Math、Date、RegExp、Error

32、JavaScript的基本資料型別和引用資料型別?你能畫一下他們的記憶體圖嗎?

  • 棧:原始資料型別(Undefined,Null,Boolean,Number,String)
  • 堆:引用資料型別(Object,Array,Function,Data)
  • 兩種型別的區別是:儲存位置不同;
  • 原始資料型別直接儲存在棧(stack)中的簡單資料段,佔據空間小、大小固定,屬於被頻繁使用資料,所以放入棧中儲存;
  • 引用資料型別儲存在堆(heap)中的物件,佔據空間大、大小不固定,如果儲存在棧中,將會影響程式執行的效能;引用資料型別在棧中儲存了指標,該指標指向堆中該實體的起始地址。不同是,你不可以直接訪問堆記憶體空間中的位置和操作堆記憶體空間。只能操作物件在棧記憶體中的引用地址。 連結

總結區別

  • 宣告變數時不同的記憶體分配: 
  • 不同的記憶體分配機制也帶來了不同的訪問機制
  • 複製變數時的不同
  • 引數傳遞的不同(把實參複製給形參的過程)
    前端技術面——(js基礎一)

33、["1", "2", "3"].map(parseInt) 答案是多少?

  • [1, NaN, NaN]因為 parseInt 需要兩個引數 (val, radix),其中radix 表示解析時用的基數。

  • map傳了 3個(element, index, array),對應的 radix 不合法導致解析失敗。

34、同步和非同步的區別?

  • 同步:瀏覽器訪問伺服器請求,使用者看得到頁面重新整理,重新發請求,等請求完,頁面重新整理,新內容出現,使用者看到新內容,進行下一步操作
  • 非同步:瀏覽器訪問伺服器請求,使用者正常操作,瀏覽器後端進行請求。等請求完,頁面不重新整理,新內容也會出現,使用者看到新內容

35、談一談let與var的區別?

  • let命令不存在變數提升,如果在let前使用,會導致報錯
  • 如果塊區中存在let和const命令,就會形成封閉作用域
  • 不允許重複宣告,因此,不能在函式內部重新宣告引數

36、瀏覽器相容問題

  • 微信H5

1.設定 overflow scroll 在IOS中滑動不流暢的問題 -webkit-overflow-scrolling: touch
2. 用bootstrap 模態框彈在IOS中彈不出的問題
cursor: pointer;

  • 微信小程式
  1. 上下兩張圖片之間的空隙,設定img為:display:block;
  2. 小程式button的邊框去不掉的時候,:after{border:none;}

37、判斷一個陣列

  • arr instancof Array
  • Array.isArray(arr)
  • Object.prototype.toString.call(arr)=='[Object Array]'

38、如何保證一個變數裡面的屬性不被修改

const object1 = { property1: 42 };

const object2 = Object.freeze(object1);

object2.property1 = 33;

39、splice和slice和substring和substr

分類 改變原資料 名稱 第一個引數 第二個引數 第三個引數
陣列方法 改變 splice start(可負值) len add
陣列方法 不改變 slice start end
字串方法 不改變 substring start end
字串方法 不改變 substr start(可負值) len

40、陣列去重

  • [...new Set(arr)]
  • Array.from(new Set(arr))

相關文章