web架構師 web前端面試100問之JavaScript(ES6/ES7)

一、什麼是原型、原型鏈,有什麼做用?

答: 原型:每個對象都與另外一個對象相關聯,那個關聯的對象就稱爲原型。
例如:函數Person有一個屬性prototype,指向一個對象,對於普通函數來講沒多意義,對於構造函數就有做用了,當使用new操做符時,會把Person.prototype(原型對象)賦值給實例的__proto__(原型實例)屬性。javascript

JS有一個原型查找機制,把原來定義在實例上的方法,放到原型對象上去,經過構造函數的new操做,會把原型對象賦值給實例的__proto__屬性,那麼當使用返回的實例去調用某一個方法的時候,若是實例自己上沒有,就去自動去實例的__proto__上去查找,這樣達到方法的複用,減小內存開銷。前端

原型鏈:每個對象,都有一個原型對象與之關聯,這個原型對象它也是一個普通對象,這個普通對象也有本身的原型對象,這樣層層遞進,就造成了一個鏈條,這個鏈條就是原型鏈。經過原型鏈能夠實現JS的繼承,把父類的原型對象賦值給子類的原型,這樣子類實例就能夠訪問父類原型上的方法了。java

2Person.prototype.constructor == Person
3
4Person.prototype.__proto__.constructor  == Object 
5
6Person.prototype.__proto__ == Object.prototype
7         
8Object.prototype.__proto__ == null

二、如何實現繼承(ES5/ES6)?

10 function Anima(name){ //父類
11                  this.name = name;
12              }
13
14              Anima.prototype.sayName = function(){
15                    console.log(this.name)
16              }
17
18              function Person(name,age){ //子類
19                  Anima.call(this,name);
20                  this.age = age;
21              }
22
23              Person.prototype = Object.create(Anima.prototype, {
24                constructor: {
25                  value: Person,
26                  enumerable: false
27                }
28              })
29
30
31            var p = new Persion("haha",12);
32
            Extends //ES6

點擊獲取 web前端全棧架構視頻課程ios

3.什麼是做用域以及做用域鏈?

答:做用域是指程序源代碼中定義變量的區域,限定一個變量可訪問的範圍的,做用域的本質是對象。在JS採用的詞法做用域,在書寫代碼的時候(定義函數的時候),做用域就已經肯定好了。 在ES6環境下,包含3個做用域,全局globel,函數做用域,快級做用域( {} ) (eval)web

做用域鏈:由多級做用域對象,逐級引用的鏈式結構。本質爲執行上下文的scope屬性,存儲全部的變量,包括局部與全局,控制變量的使用順序。面試

var b = 10; //1:輸出?2:改造代碼輸出10或20
(function b(){
    b = 20;
    console.log(b); 
})();

var b = 10;
(function b(b) { 在這個函數b是一個常量,在函數b內部是可使用的,可是不能修改,若是加上use strict 嚴格模式就會報錯。
 window.b = 20;
 console.log(b) //輸出10
})(b)
var a = 10;
(function () {
    console.log(a)
    a = 5
    console.log(window.a)
    var a = 20;
    console.log(a)
})()

4.什麼是閉包,閉包的好處和壞處分別是?

答:當函數能夠記住並訪問外部做用域時,就產生了閉包,那個外部做用域就稱爲閉包。axios

造成的緣由:外層函數的做用域對象沒法釋放。
做用:保護一個變量,重用一個變量。壞處:使用不當,會形成內存泄漏。api

大白話來解釋:函數A和函數B,當內部函數B引用了A 的局部變量時,函數A 稱爲閉包
緣由是:JS是詞法做用域,B的做用域鏈上有對A執行環境的引用(這個執行環境用函數來表示),A的執行環境AO就不會回收。跨域

五、什麼是this,this的經常使用方式有哪些?如何改變this的指向?

答:JS在運行過程當中會產生執行上下文環境(context),context記錄了包含函數在哪裏被調用,做用域scope,this等信息。this就是context的其中一個屬性,會在函數的執行過程當中使用。This是在運行時候綁定的,它指代的上下文對象取決於函數調用的各類條件。
this提供了一種優雅的方式來隱式的傳遞一個對象的引用,因此在函數中使用this能夠更加方便的複用函數。數組

一、全局使用 this === window 不多使用
二、函數當中 在全局調用這個fn() this === window
三、在方法當中使用 this === 調用當前這個函數的所在的對象啊
四、構造函數this執向的是 new 建立出來的實例對象啊
五、DOM事件處理函數中的this,指向當前的DOM節點
六、經過 bind,call,apply 操做符來顯示的設置 this的指向

bind:綁定函數裏面的this,返回新函數,
     call,apply:綁定並執行這個函數,前者傳參是「,」隔開,後者是數組

七、ES6的箭頭函數 箭頭函數沒有本身的this,父做用域的this

var x = 3;
  var foo = {
     x: 2,
     baz: {
      x: 1,
      bar: function() {
         return this.x;
        }
      }
   }

  var go = foo.baz.bar;
  go()?
foo.baz.bar()?


//綜合面試題
function Foo() {
    Foo.a = function() {
        console.log(1)
    }
    this.a = function() {
        console.log(2)
    }
}
Foo.prototype.a = function() {
    console.log(3)
}
Foo.a = function() {
    console.log(4)
}
Foo.a();
let obj = new Foo();
obj.a();
Foo.a();

6.手寫bind,call,apply函數

答案:以上都是Function原型上的方法。

Function.prototype.myCall = function(context,...args){//綁定並執行
                //執行函數
              var fn = this;
              context.fn = fn;
              context.fn(...args);
              delete context.fn
          }

          Function.prototype.myBind = function(context){//綁定返回新的執行函數
            //判斷調用者是否是函數
            if(typeof this != 'function'){
                throw new Error("Error")
            }
            //截取傳遞的參數
            let args = [...arguments].slice(1);
            var _this = this;//保存一下當前的調用者  
            return function F() {
              return _this.apply(context,args.concat([...arguments]))
            }
          }

7.什麼是深、淺拷貝,請寫出代碼

答:淺拷貝,就是複製一個對象,當對象的屬性值沒有引用類型的時候。

Object.assign 迭代(for..in for..of object.enteries) 擴展運算符等。

反之若是對象中還有引用類型,連着引用類型一併拷貝稱爲深拷貝。

JSON對象的方法(會忽略到值爲函數和null的屬性),遞歸。
function deepCopy(obj){
              //判斷對象的類型
            var newObj =  Array.isArray(obj)?[]:{};
            if(obj && typeof obj == "object"){
                  //迭代
                  for(var key in obj){
                        if(typeof obj[key] == 'obj'){
                          newObj[key] = deepCopy(obj[key])
                        }else{
                          newObj[key]  = obj[key]
                        }     
                  }
            }
            return newObj
    }

八、什麼是Ajax,如何封裝一個Ajax?Get請求與 Post請求的區別?

答:Ajax的全稱是異步的js與xml技術,經過它與後臺服務器進行數據交換,可使網頁實現異步更新,言外之意是在不從新加載整個頁面的狀況下,對網頁進行局部更新。

1.nex xmlhttprequset對象
     2.open(method,url,false)
     3.綁定redaystatechange事件
     4.調用send方法,若是是post請求,能夠傳遞參數

前端的請求方式除了經常使用Get和Post,還有update,delete,put等(restful api設計)
GET 請求可被緩存,保留在瀏覽器歷史記錄中 ,請求的參數是直接跟在URL上,所以不該傳遞敏感數據。
GET 請求有長度限制(2048字符),IE和Safari瀏覽器限制2k;Opera限制4k;Firefox,Chrome限制8k 。
GET 請求一般只應當用於從後臺獲取數據。

POST 請求不會被緩存,不會保留在瀏覽器歷史記錄中
POST 請求對數據長度沒有要求。
POST 請求一般用於日後臺提交數據。

9.說一些ES六、ES7新特性。

答: let,count快級做用域;解構,從對象和數組中提取值;箭頭函數;字符串模版;擴展運算符...;對象的簡寫;module;promise(async);class;對原生對象的擴展(新增長了不少方法) ;for-of (Object.keys,values,entries等);Symbal();

不經常使用的proxy,reflect,generate函數

十、什麼是Promise對象,如何使用?

答:Promise是解決異步回調的ES語法的標準,一般用來解決異步嵌套和多異步同時完成回調等問題。

Promise是一個構造函數,至關於一個容器,把異步代碼包裹在裏面,promise有三個狀態(pending(進行中)、fulfilled(已成功)和rejected(已失敗))初始化爲pending,當異步請求成功後調用resolve函數,狀態從pending--->fulfilled,失敗的時候調用reject,狀態從pending--->rejected。狀態不可逆。
  缺點:書寫麻煩,不能實現異步代碼,同步執行的需求(配合async函數使用便可)

十一、什麼是跨域,解決跨域經常使用的方式有哪些?

答:跨域是瀏覽器端行爲,根據同源策略,當請求的協議、域名、端口只有一個不一樣,就會跨域,跨域是瀏覽器爲了安全存在的機制,瀏覽器會把跨域請求的數據去掉,同行報錯。

在實際開發不免會出現跨域的狀況,解決方案一般有

1.JSONP技術,利用了script的src屬性沒有跨域限制
2.CORS,當在相應頭信息中添加access-control-allow-origain屬性,瀏覽器讀取到就會容許返回數據。後臺配置,或者下一個瀏覽器插件便可。
3.後臺代理(Node)
4.Iframe域的提高(不多)

十二、什麼是函數的防抖、節流,並手寫基本代碼

答:防抖和節流都是爲了提高運行效率,減小函數的執行次數。

防抖:把屢次函數執行,合併成一次執行
function debounce(fn,delay){ //fn真正執行的函數,delay間隔時間
                var timer = null;
                 return function(){
                    var args = arguments;
                    var that = this;
                    if(timer) clearTimeout(timer)
                    timer = setTimeout(function(){
                        fn.apply(that,[...arguments])
                    },delay)
                 }

       }

節流 :規定一個單位時間,在單位時間內觸發一個事件回調,觸發時超過間隔時間則執行,不然不執行。

function throttle(fn,gapTime){
          let _lastTime = null;
          return function(){
            var that = this;
            var args = arguments;
            let _nowTime = + new Date();
            if(_nowTime-_lastTime > gapTime || !_lastTime){
               fn.apply(that,args);
               _lastTime = _nowTime;
            }
          }
     }

1三、什麼事件循環(Event Loop)?

答:js是非阻塞單線程語言,js在執行過程當中會產生執行環境,執行環境會被順序的加入到執行棧,當遇到異步任務,會添加到task隊列當中,執行同步棧,當同步棧執行完之後,event loop 就會從異步task隊列當中提取要執行的代碼放到執行棧中。這個一個過程稱爲事件循環。因此JS的異步仍是同步過程。

console.log('script start')

          setTimeout(function() {
            console.log('setTimeout')
          }, 0)

          new Promise(resolve => {
            console.log('Promise')
            resolve()
          })
            .then(function() {
              console.log('promise1')
            })
            .then(function() {
              console.log('promise2')
            })

          console.log('script end')
          //輸出結果?

1五、前端安全你有了解嗎?什麼是XSS攻擊和CSRF 跨站請求僞造?怎麼預防?

答:前端的安全問題,在工做過程當中會注意這些問題。

一、XSS 代碼注入問題,一般不信任用戶的輸入,轉義輸入輸出內容()encodeURIComponent),括號 尖括號等。利用用戶對站點的信任

   二、CSRF 跨站請求僞造 
            是一種挾制用戶在當前已登陸的web應用中執行非本意的攻擊
            大白話:利用用戶登陸態發起惡意請求
            網站對用戶的信任

添加驗證碼(體驗稍微差一些),不讓第三方訪問cookie 對cookie設置 samesite, 請求驗證 加 token ,

三、密碼問題:對密碼進行加密(MD5等)

16.如何處理精度丟失問題?

答:產生的緣由:JS使用Number類型表示一個數字,使用64位。
在這裏插入圖片描述

計算機先把10進制轉位2進制,0.1和0.2轉成二進制的時候還會無限循環,因爲有51位位數的限制,多餘的會被裁掉,因此在進制之間轉換就會丟掉精度。
一般能夠把小數乘以倍數轉成正整數,計算完後再轉回去。
parseFloat((0.1 + 0.2).toFixed(10))

16.前端經常使用請求數據的方式有哪些,並說出各自的區別。

答:前端進行網絡請求經常使用的form,Ajax,fetch

經常使用的庫文件Jquery或者axios等。
  
  Form提交數據頁面會刷新,使用體驗不佳。
  Ajax是一個綜合技術,能夠實現異步更新頁面內容。使用起來方便,一般使用JQ的封裝,會額外的JS加載代價。
  Fetch是新的API,比較底層。目前瀏覽器兼容性問題多一些,好比老版本不會攜帶cookie,不能直接傳遞JS對象做爲參數,不支持JSONP等

17.如何檢測一個對象必定是數組?

答:一、Object.prototype.toString.call(),前提是toString方式沒有被重寫。
二、instanceof 內部機制是經過判斷對象的原型鏈中是否是能找到類型的 prototype。
[] instanceof Object; // true
三、Array.isArray() ES5新增的方法,兼容性稍微差一些。

18.JS加載會阻塞頁面渲染嗎?會的話該怎麼解決呢?

答:會

defer:並行下載,在頁面解析完後執行,會按照script的順序執行。(經常使用)

async:異步下載代碼,下載完畢後離職執行代碼,不會按照頁面的script順序。

20.常見前端性能優化有哪些?
答:
1:加載優化

CDN,文件壓縮混淆合併,按需加載(異步組件),前端緩存,瀏覽器緩存(cache-control,exprices) 
     
     DNS預先解析,服務器渲染 nuxt,next(SEO),圖片懶加載

2:腳本優化

減小合併DOM操做(createDocumentFragment),CSS3代替js動畫,緩存變量,用requestAnimationFrame代理setTimeout,減小reflow與repain,事件代理,開啓GPU渲染tranfrom:translateX(0)

3:圖片優化

雪碧圖(減小請求),使用SVG和iconfont(字體圖片)代替圖片,圖片壓縮

更多前端面試相關和性能優化前端自動化測試視頻教程請私信或點擊獲取。

相關文章
相關標籤/搜索