前端面試題集錦-2021年前端面試題收集題庫1

1.說說Javascript中對象的幾種創建模式

  • 對象-繼承-面向對象
    • 創建對象第一個想到的關鍵字是 new
    • 創建對象的目的是實現繼承,繼承部分通用屬性
    • 問題可以轉換成 : JavaScript如何實現對象的繼承,繼承的形式
  • 構造函數
    • 首先定義一個構造函數,可以傳入構造參數,demo如下:
          function Student(name,sex){
              this.name = name
              this.sex = sex
              this.sayName = function(){
                  console.log(this.name)
              }
          }
          var student_1 = new Student('張三','male')
      
    • 限制和優勢
      • 必須使用 new 關鍵字
      • 創建一個對象需要使用一次new語句
      • 屬性和方法直接賦予this對象
      • 限制1:每個對象的屬性和方法都需要創建一遍,如果是公用的屬性會造成浪費
      • 限制2:多次創建相似對象,需要重複的進行new動作,無法快速創建
  • 快速批量創建對象的 工廠模式
    • 使用一個工廠函數,入參接受構造參數,返回創建的對象,避免重複的new關鍵字
          function factory(name,sex){
              var obj = new Object()
              obj.name = name
              obj.sex = sex
              obj.sayName = function(){
                  console.log(this.name)
              }
              return obj
          }
          var person_1 = factory('zhangsan','male')
          var person_2 = factory('lisi','female')
      
    • 限制和優勢
      • 生成相似的同類對象避免多次重複的new關鍵字
      • 限制:只能構造同類元素
  • 避免重複屬性性能浪費的 原型模式
    • 每個函數都有一個原型屬性指針prototype,指向一個原型對象,所有實例的該屬性指向同一個對象,並不會重複創建對象,所以再原型對象裏面添加屬性,可以避免實例重複創建對象的性能浪費
      ```:javacsript
      function student_proto(){

          }
          student_proto.prototype.sayNme = funciton(){
              console.log(this.name)
          }
          student_proto.prototype.sex = 'male'
          student_proto.prototype.name = 'zhangsan'
      
          var student_1 = new student_proto()
      ```
      
    • 如果實例上沒有某個屬性,就會往上向原型鏈上查找,會拿到prototype上面的統一的一個對象屬性

    • 如果實例上有這個屬性則會直接返回實例屬性,如果原型鏈上也沒有這個屬性那麼就會返回Undefined

    • 限制:實例對原型對象引用屬性的修改會修改所有實例的原型屬性,沒法做到獨立性

  • 組合使用 原型模式和構造函數
    • 在使用構造函數的保證實例屬性獨立的前提下,原型屬性也使用,實現混合模式
      function Student(name,sex,grade){													
          this.name = name;
          this.sex = sex;
          this.grade = grade;
      }
      
      Student.prototype.sayName = function(){
              console.log(this.name);
      }
      Student.prototype.school = 'Joooh school';
      
  • 動態原型模式
    • 原理:還是把所有的信息都封裝在構造函數裏面,但是爲了避免方法的重複定義和性能損耗,在定義重複方法之進行了一個判斷,如果this.function 已經存在則不在進行重複定義,如果不存在,將原型鏈上添加上該方法
    • demo
      function Person(name, age, job){
      
          //屬性
          this.name = name;
          this.age = age;
          this.job = job;
      
          //方法
          if (typeof this.sayName != "function"){
      
              Person.prototype.sayName = function(){
                  alert(this.name);
              };
      
          }
      }
      
      var friend = new Person("Nicholas", 29, "Software Engineer");
      friend.sayName();
    
  • 寄生構造函數模式
    • 原理:Javascript 中構造函數如果有返回值的情況會怎麼樣

      • 無返回值: 實例爲正常實例化對象
      • 有返回值但是返回值爲非引用類型:實例爲正常實例化對象
      • 有返回值並且返回值爲引用類型:實例爲返回值引用對象
    • 所謂寄生構造函數就是創建一個函數,然這個函數只是封裝創建對象的代碼,然後再返回新創建的對象。

      ```:javascript
      function Person(name,age,job){
      
      var o = new object();
      
      o.name = name;
      
      o.age=age;
      
      o.job=job;
      
      o.sayName = function(){
      
          alert(this.name)  
      
      }
      
      return o;  
      
      }
      
      var friend = new Person(name1,age1,job1)
      
      friend.sayName(); // name1
      ```
      
    • 構造函數裏面通過一個函數返回引用對象,不推薦使用,並且無法通過Instanceof 判斷所屬關係


Javascript中如何實現異步編程

  • 回調函數
    • 原理:在需要持續很長的代碼塊結束位置調用回調函數,可以保證代碼在結束時調用,後者等待前者的結果
    • 缺點:不利於代碼維護,冗長,跳轉調用閱讀困難,控制反轉
  • promise
    • 原理:ES6中註冊promise對象,根據異步任務執行狀態,調用promise的resolvereject方法,將promise狀態置爲resolvedrejected,promise對象會在狀態轉變時自動調用resolve回調或者是reject回調
    • 優點:代碼結構優秀,可以鏈式調用
  • 發佈/訂閱模式
    • 相當於有個事件bus,任何監聽了bus事件的訂閱者,在bug觸發一定事件時都會執行相應回調函數
  • 事件監聽
    • 事件監聽其實也是發佈訂閱模式的一種形式,在事件觸發時,所有訂閱者的對應函數都會被執行,常用的是vue的bus
  • async/await
    • ES6 中可迭代對象,可以使用next()生成,下一個序列的可迭代屬性,在手動調用next方法時,只要返回值done不是true,則會阻塞下一次next()的調用
    • 所以通過next 的阻塞作用,使用asyncawait達到異步阻塞,在前者執行完之前不會執行後者,達到異步的效果
    • 可以結合Promise同時使用

Javascript 的同源策略

  • 概念:JavaScript只能讀取和所屬文檔同源的窗口和文檔的屬性
    • 判斷來源:指腳本本身的來源並不作爲同源依據,而是指腳本所屬文檔的來源作爲判斷依據
    • 同源:協議,主機,端口必須全部相同

爲什麼JavaScript會有同源策略限制

  • 避免跨域跨來源的安全問題

爲什麼說Function函數在JavaScript中是第一類對象

  • 函數擁有對象能做的一切能力
    • 可以動態創建
    • 可以當作引用賦值
    • 可以擁有自己的屬性和方法
    • 可以分配變量,可以將他們的引用複製到其他變量,可以被拓展或者刪除
    • instance 函數和Object都是true,函數的原型鏈最上層也是Object,擁有對象的所有原型屬性和方法

JavaScript中函數聲明和函數表達式的區別

  • 什麼是函數聲明
    • function type(){ } 類似這樣,聲明一個名叫type的函數
    • var type = function(){} 類似這樣則是函數表達式,並且把函數表達式賦值給一個變量
  • 主要就是函數聲明會和var聲明變量一樣,會有變量提升的問題
  • JavaScript中定義函數的四種方式
    • 函數聲明
    • 函數表達式
    • 箭頭函數
    • new Function()

JavaScript如何刪除cookie中的一個鍵值對

  • 原理:
    • document.cookie 在賦值時是設置單個cookie,但是獲取document.cookie的時候是返回所有的cookie
    • 在需要刪除的cookie鍵值對後面增加一個exires=時間戳exires鍵值對,瀏覽器就會立刻刪除該cookie鍵值對,注意此處的時間戳必須是UTC或者是GMT時間不能是本地時間
    • 需要將document.cookie => .split(';')=>拆分成數組,for of 遍歷,在需要修改的鍵值對後面進行添加exire鍵值對

手寫一個方法求字符串的字節長度

  • 思路:
    • 字符串自帶屬性.length,可直接拿到字符長度
    • 遍歷字符串,通過charCode識別時候是中文字符,如果是中文字符>255 則字節數額外+1

attribute 和 property的區別

  • attribute : 特性,特性節點(attribute node),每個dom節點都有有個attribute屬性用來存儲特定的attribute node屬性節點
  • property :屬性,每個dom節點,如果當作普通Object看,property就是存儲在Object中的一個鍵值對
  • 設置方法不一樣: attribute 需要setAttribute方法設置,property直接.語法設置
  • 刪除方式不一樣: attribute 需要removeAttribute方法設置,property則是使用Objectdelete 方法

延時腳本在JavaScript中的作用

  • deferasync 屬性對腳本加載的意義不一樣
  • 相同點: 都會使腳本的加載過程不阻礙html的解析
  • 不同點: defer 延時即使腳本加載完成,也會等待html解析完畢再執行腳本,而 async 則是異步加載腳本,腳本一加載完成則會立即執行腳本,可能還是會阻礙html解析
  • 相同作用:都是爲了更好的html體驗,減少白屏時間,優化用戶體驗

閉包是什麼,閉包的優缺點

  • 閉包
    • 函數:封裝作用域
    • 閉包:利用函數封裝作用域的特性,實現了私有域變量的封裝,同時暴露出方法,允許獲取或者操作私有域變量
    • 實現:函數-》 函數作用域的變量聲明 -》 暴露方法允許操作或者修改變量
  • 優點:私有域的變量,防止變量污染,防止全局污染,私有屬性
  • 缺點:內存消耗巨大,變量不會自動回收(變量引用一直都在)

如何判斷一個對象是否屬於一個類

  • instanceof
    • object instanceof Object 右邊參數是否存在左右對象的原型鏈上,存在返回 true 不存在返回 false
  • constructor
    • object.constructor === Object 一個實例在創建過程中,prototype 中會自動創建一個constructor 屬性,並且指向這個構造函數

是否存在一個函數,只在當前對象查找屬性,不會順原型鏈查找

  • hasownproperty
    • 返回值:一個 boolean 值,該對象本身是否擁有該屬性
    • 可能會有坑: hasOwnProperty 也是 Object 原型鏈上一個屬性,可以被重寫

document.write和innerHTML的區別

  • 是否重繪整個頁面:
    • document.write在修改html片段之後會重繪頁面
    • innerHtml修改html片段 會重繪部分頁面片段

在JavaScript中讀取文件的方法是什麼

  • JavaScript環境區分
    • node環境:
      • fs 庫
      // 1. 使用 require 方法加載 fs 核心模塊
      var fs = require('fs')
      // 2. 讀取文件
      //    第一個參數就是要讀取的文件路徑
      //    第二個參數是一個回調函數
      //        成功
      //          data 數據
      //          error null
      //        失敗
      //          data undefined沒有數據
      //          error 錯誤對象
      fs.readFile('read.txt', function (error, data) {
      // 在這裏就可以通過判斷 error 來確認是否有錯誤發生
      if (error) {
          console.log('讀取文件失敗了')
      } else {
          console.log(data.toString())
      }
      })
      
      
    • 瀏覽器環境:
      • 後端讀取文件,返回前端解析 前端通過 xhr http 請求拿取文件內容
                  function readAjaxFile(url) {
                      // 創建xhr
                      var xhr = new XMLHttpRequest();
                      // 監聽狀態
                      xhr.onreadystatechange = function() {
                      // 監聽狀態值
                      if(xhr.readyState === 1 && xhr.status === 200) {
                      console.log(xhr.responseTest)
                      }
                      }
                      // 打開請求
                      xhr.open('GET', url, true)
                      // 發送數據
                      xhr.send(null)
                      }
      
      • 前端通過input 上傳文件
          let file  =  document.queryselector('file-input')[0].file[0]
          let reader = new FileReader()
          reader.readAsText(file)
          reader.onload = function(data) {
              console.log(data, this.result);
              }
      

Javascript如何分配對象屬性

  • 對象賦值?
    • . 屬性點操作賦值 obj.test = 1
    • [] 方括號屬性操作 obj['test'] = 1
    • 區別:方括號內部允許變量動態值,點屬性只能直接獲取屬性
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章