js base

  • var、let、const的區別;
    • var 會變量提高
    • let 聲明的變量只在它所在的代碼塊有效
    • const聲明後不能再修改其指向的目標,假如const指向的是一個對象/數組,那麼雖然不能更改指向目標,可是能夠更改對象和數組內部的值;
  • class聲明一個類時,存在變量提高麼?爲何?
    • 不存在。由於要方便類的繼承,先聲明子類再聲明父類;
  • const 聲明一個對象,如何讓對象內部的屬性的值也沒法改變?
    • 使用Object.freeze()鎖死(es5新增特性);對數組等引用類型的值,仍是能修改的;
  • javascript有哪幾種數據類型?如何判斷?
    • 六種基本數據類型:
    • undefined
    • null
    • string
    • Boolean
    • Symbol
    • 一種引用類型
    • object(function/Date/RegExp/Number/String/boolean)
    • 如何判斷?
      • typeof(1) //number沒法區分引用類型都返回‘object’
      • instanceof //[] instanceof Array; //true 可是沒法對原始類型進行判斷。通常都是判斷爲object後再使用instanceof具體判斷。
      var obj = {};
      obj instanceof Object;           //true
      
      var arr = [];
      arr instanceof Array;           //true
      
      var now = new Date();
      now instanceof Date;             //true
      
      var func = function(){};
      func instanceof Function;        //true
      
      var str = "string";
      str instanceof String;           //false
      複製代碼
      • Objectl.prototype.toString.call()通用的來判斷原始數據類型和引用數據類型。
      var num1 = 1;
      var num2 = new Number(1);
      Object.prototype.toString.call(num1) == "[object Number]";      //true
      Object.prototype.toString.call(num2) == "[object Number]";      //true
      
      var arr = [];
      Object.prototype.toString.call(arr) == "[object Array]";        //true
      
      var func = function(){};
      Object.prototype.toString.call(func) == "[object Function]";   //true
      
      function A(){};
      var a = new A();
      Object.prototype.toString.call(a) == "[object Object]";   //true
      複製代碼
    • constructor
    console.log([].constructor == Array);
    console.log({}.constructor == Object);
    console.log("string".constructor == String);
    console.log((123).constructor == Number);
    console.log(true.constructor == Boolean);
    複製代碼
  • Symbol(es6)特色以下:
    • 表示獨一無二的值
    • 聲明時不能使用new Symbol(),而是 Symbol()
    • 聲明時能夠加參數,用於描述
    • 做爲key時不能被遍歷
    • 如何聲明兩個相等的Symbol變量?
    let a = Symbol.for('a');
    let b = Symbol.for('a');
    a === b;    // true
    複製代碼
  • 檢查一個對象是否存在的方法:
    • this指向問題
    if(!obj){ // 控制檯會報錯obj is not defined
          obj = {};
        }
       if(!this.obj){
          alert('1')
          this.obj = {};
        }
        if(!this.hasOwnProperty('obj')){
              alert('2')
              this.obj = {};
        }
        if(!window.obj){
              alert('3')
              window.obj = {};
        }
    複製代碼
  • Promise是什麼?
    • 含義: 是異步編程的一種解決方案, 簡單說就是一個容器,裏面保存着某個將來纔會結束的事件(一般是一個異步操做)的結果。從語法上說,Promise 是一個對象,從它能夠獲取異步操做的消息。
    • 使用場景:異步請求,好比ajax
    • 哪些狀態:pending,resolved,rejected.
    • 若是內部拋錯,可是沒有被捕獲,這個沒被捕獲的錯誤接下來會發生什麼事情?冒泡。
    • 如何捕獲錯誤:最後catch;then的第二個參數。
    • 不能夠用try catch 捕獲,由於是異步編程。
  • 寫一個簡易的promise
    //todo
    複製代碼
  • async、await 的使用場景是什麼?
    • 連續的異步請求,下一步的異步請求依賴於前一步的異步請求結果;
  • 假若有A、B、C三個異步請求,異步請求C依賴於異步請求A和B的結果(即A和B完成後再發起C),那麼你會如何實現它?
    • Promise.all();
    • 設置狀態分別標記A和B,A、B完成後會去修改本身的完成標記,而後檢查全部的狀態標記,假如都是完成狀態,而後去執行異步請求C。
  • 檢測一個變量是否爲對象?
typeof xx === 'object' // error null也是對象。
(xx !== null) && (typeof xx === "object") // ok

複製代碼
  • 判斷var是的是不是全局變量。
var x = 0;
    function text() {
      return this.x;
    }
    let o = {};
    o.x = 1;
    o.m = text;
    // o.m.apply(); //  console.log('x',x) 0 this指向全局
    o.m.apply(o); //  console.log('x',x) 1 this指向var,var的this仍是全局。
複製代碼
  • this指向問題1
function f1() {
      var n = 1;
      aAdd = function () { // 沒有用var直接將值賦值給了window。
        console.log('n', n); // 也能夠獲取n=1
        n += 1;
      }
      function f2() {
        return n;
      }
      return f2;
    }
    var result = f1();
    aAdd();// 回調用此函數,而且加1.
    result();
    console.log('result', result()); // 999
    console.log('aAdd', aAdd);
複製代碼
  • this指向問題2
var x = {
  name: 'bw2',
  getName1: function() {
    console.log(this) // {name: "bw2", getName1: ƒ}
  },
  getName2: function() {
    setTimeout(() => {
      console.log(this) // {name: "bw2", getName1: ƒ}
    },0)
  },
  getName31: () => {
    console.log(this) //Window
  },
  getName32: function() {
    return function() {
      console.log(this) // Window
    }
  }
}
x.getName1()  // {name: "bw2", getName1: ƒ}
x.getName2()  // {name: "bw2", getName1: ƒ}
x.getName31()  // Window {stop: ƒ, open: ƒ, alert: ƒ, confirm: ƒ, prompt: ƒ, …}
x.getName32()()  // Window {stop: ƒ, open: ƒ, alert: ƒ, confirm: ƒ, prompt: ƒ, …}
複製代碼
  • 法則一:對象方法中的this指向對象自己(箭頭函數形式的除外)
var x = {
  name: 'bw2',
  getName1: function() {
    console.log(this)
  }
}
x.getName1()  // {name: "bw2", getName1: ƒ}
複製代碼
  • 多層嵌套函數中的this指向等同於包含該this的最近一個function的this
    • 箭頭函數沒有獨立的this做用域,因此繼續往外層走,走到了getName: function(){}。那麼就是他了,this指向等同於這個function內部的this指向。根據法則一,this指向對象自己。
var x = {
  name: 'bw2',
  getName2: function() {
    console.log(this)  // 等同於此處的this
    setTimeout(() => {
      console.log(this)  // 箭頭函數沒有this,繼續往上找,原始的this位置
    },0)
  }
}
x.getName2()  // {name: 'bw2', getName1: ƒ}
複製代碼
  • 法則三:箭頭函數以及非指向對象方法中的function的狀況下this指向window
var x = {
  name: 'bw2',
  getName31: () => {
    console.log(this) // window
  },
  getName32: function() {
    return function() {
      console.log(this) //window
    }
  }
}
x.getName31()  // Window {stop: ƒ, open: ƒ, alert: ƒ, confirm: ƒ, prompt: ƒ, …}
x.getName32()()  // Window {stop: ƒ, open: ƒ, alert: ƒ, confirm: ƒ, prompt: ƒ, …}
複製代碼
  • 寫個函數‘get-element-by-id’ 返回‘getElementById’
function get(str) {
        var strArray = str.split('-');
        for(let i = 0 ;i < strArray.length; i++){
            if(i > 0){
                strArray[i] = strArray[i].slice(0, 1).toUpperCase() + strArray[i].slice(1)
            }else {
                strArray[i] = strArray[i];
            }
        }
        return strArray.join('');
    }
    let b = get('get-element-by-id');
複製代碼
  • 請描述一下 cookies,sessionStorage 和 localStorage 的區別?
    • 是否傳遞給服務器。cookie是網站爲了標示用戶身份而儲存在用戶本地終端(Client Side)上的數據(一般通過加密)。 cookie數據始終在同源的http請求中攜帶(即便不須要),記會在瀏覽器和服務器間來回傳遞。sessionStorage和localStorage不會自動把數據發給服務器,僅在本地保存。
    • 大小。cookie數據大小不能超過4k。 sessionStorage和localStorage,雖然也有存儲大小的限制,但比cookie大得多,能夠達到5M或更大。
    • 時間。localStorage 存儲持久數據,瀏覽器關閉後數據不丟失除非主動刪除數據; sessionStorage數據在當前瀏覽器窗口關閉後自動刪除。 cookie設置的cookie過時時間以前一直有效,即便窗口或瀏覽器關閉。
  • 說幾條寫JavaScript的基本規範
    1.不要在同一行聲明多個變量。
    2.請使用 ===/!==來比較true/false或者數值
    3.使用對象字面量替代new Array這種形式
    4.不要使用全局函數。
    5.Switch語句必須帶有default分支
    6.函數不該該有時候有返回值,有時候沒有返回值。
    7.For循環必須使用大括號
    8.If語句必須使用大括號
    9.for-in循環中的變量 應該使用var關鍵字明確限定做用域,從而避免做用域污染。
    複製代碼
  • null和undefined的區別?
    • null: Null類型,表明「空值」,表明一個空對象指針,使用typeof運算獲得 「object」,因此你能夠認爲它是一個特殊的對象值。
    • Undefined:Undefined類型,當一個聲明瞭一個變量未初始化時,獲得的就是undefined。
    • console.log(null==undefined)//true。console.log(null===undefined)//false
    • null 用法:
      • 做爲函數的參數,表示該函數的參數不是對象。
      • 原型鏈的終點。
    • undefined表示"缺乏值"
      • 變量被聲明瞭,但沒有賦值時,就等於undefined。
      • 調用函數時,應該提供的參數沒有提供,該參數等於undefined。
      • 對象沒有賦值的屬性,該屬性的值爲undefined。
      • 函數沒有返回值時,默認返回undefined。
  • 什麼是深拷貝和淺拷貝,如何作深拷貝?
    • 深拷貝含義:它不但拷貝目標對象的第一層屬性,並且還遞歸拷貝目標對象的全部屬性
    • 淺拷貝含義:淺拷貝只會將對象的各個屬性進行依次複製,並不會進行遞歸複製,也就是說只會進行賦值目標對象的第一層屬性。
//淺拷貝一、ES6:object.assign()
var a = { name : 「hello」 };
var b = Object.assign( { },a );
b.name = 「hi」;
console.log(a);
複製代碼
// 淺拷貝二、展開運算符……
擴展運算符用三個點號表示,功能是把數組或類數組對象展開成一系列用逗號隔開的值
var a = { name : 「hello」 };
var b = { …a};  
b.name = 「hi」;
console.log(a);
複製代碼
//淺拷貝三、本身封裝函數實現for in
var a = { name : 「hello」 };
var b = copy(a);
    b.name = ‘hi’;
    console.log(a);
function copy(obj){
    var result = { };
    for(var attr in obj ){
        result [attr] = obj[attr];
    }
    return result;
}
複製代碼
```
//深拷貝1
var dest = JSON.parse(JSON.stringify(target));
//深拷貝2
var deepCopy= function(source) { 
        var result={};
        for (var key in source) {
            result[key] = typeof source[key]===’object’? deepCoyp(source[key]): source[key];
         } 
       return result; 
    }
// 深拷貝3 reduce
function deepClone(a) {
  const keys = Object.keys(a)
  return keys.reduce((memo, current) => {
    const value = a[current]
    if (typeof value === 'object') {
      return {
        ...memo,
        [current]: deepClone(value),
      }
    }
    return {
      ...memo,
      [current]: value,
    }
  }, {})
}
var a = {
  val: 1,
  desc: {text: 'a'},
}
var b = deepClone(a)
//深拷貝4 第三方類庫
Lodash  merge函數
immutable 
```
複製代碼
  • call、apply和bind方法的用法以及區別?
    • call 方法第一個參數是要綁定的this,後邊傳入是參數列表,當第一個參數是null、undefined的時候,默認指向window。
    • 好比fn.call(obj,...arguments)
    var obj = {
        message: 'My name is: '
    }
    function getName(firstName, lastName) {
        console.log(this.message + firstName + ' ' + lastName)
    }
    getName.call(obj, 'Dot', 'Dolby')
    複製代碼
    • apply接收兩個參數,第一個是要綁定的this,第二是參數數組。當第一個是null、undefined的時候默認指向window。
    • 好比:fn(obj,[...])
    var obj = {
        message: 'My name is: '
    }
    function getName(firstName, lastName) {
        console.log(this.message + firstName + ' ' + lastName)
    }
    getName.apply(obj, ['Dot', 'Dolby'])// My name is: Dot Dolby
    
    複製代碼
  • bind第一個參數是this,從第二參數開始是接收的參數列表。區別在於bind方法返回值是函數以及bind接收的參數列表的使用。
var obj = {
    name: 'Dot'
}

function printName() {
    console.log(this.name)
}

var dot = printName.bind(obj)
console.log(dot) // function () { … }
dot()  // Dot
複製代碼
//一樣bind也能夠有多個參數,而且參數能夠執行的時候再次添加,可是要注意的是,參數是按照形參的順序進行的。
var a = {
    user:"追夢子",
    fn:function(e,d,f){
        console.log(this.user); //追夢子
        console.log(e,d,f); //10 1 2
    }
}
var b = a.fn;
var c = b.bind(a,10);
c(1,2);
複製代碼
  • call、apply和bind函數存在的區別:
    • 返回值不一樣:bind返回對應函數, 便於稍後調用。apply, call則是當即調用。
    • 在 ES6 的箭頭函數下, call 和 apply 將失效。
    • call和apply的第二個參數不一樣。call第二個參數是單個系列。bind能夠多個參數,依次是行參。apply第二參數是[...]。
  • js裏面,變量聲明方式一共幾種?
    • var let const function class import
  • 瀏覽器基礎對象有哪幾個?
    • window、navigator、screen、history、location。
  • 頁面刷新有哪幾種方式?
    • location.reloading;locatoin.href = href。location.replace。
  • Navigator如何區分是Android仍是iOS(若是作過移動端開發);若是區分是否在微信中?(若是有作過移動端微信開發)
    • 基礎考點:至少要能答出經過UA區分,答不出扣分。
    • 一階考點:考察對UA有實際使用經驗
    • 二階考點:能講出Android的一些奇葩瀏覽器UA(如Adr、QQ瀏覽器等),說明經驗豐富
  • websocket 是什麼怎麼用?如何兼容低瀏覽器?
    Adobe Flash Socket 、
      ActiveX HTMLFile (IE) 、
      基於 multipart 編碼發送 XHR 、
      基於長輪詢的 XHR
    複製代碼
    // websocket怎麼用?
    
    複製代碼
  • offsetWidth/offsetHeight,clientWidth/clientHeight與scrollWidth/scrollHeight的區別?
    • offsetWidth/offsetHeight返回值包含content + padding + border,效果與e.getBoundingClientRect()相同
    • clientWidth/clientHeight返回值只包含content + padding,若是有滾動條,也不包含滾動條
    • scrollWidth/scrollHeight返回值包含content + padding + 溢出內容的尺寸
  • XMLHttpRequest通用屬性和方法?
    • readyState:表示請求狀態的整數,取值
      • UNSENT(0):對象已建立
      • OPENED(1):open()成功調用,在這個狀態下,能夠爲xhr設置請求頭,或者使用send()發送請求
      • HEADERS_RECEIVED(2):全部重定向已經自動完成訪問,而且最終響應的HTTP頭已經收到
      • LOADING(3):響應體正在接收
      • DONE(4):數據傳輸完成或者傳輸產生錯誤
    • onreadystatechange:readyState改變時調用的函數
    • status:服務器返回的HTTP狀態碼(如,200, 404)
    • statusText:服務器返回的HTTP狀態信息(如,OK,No Content)
    • responseText:做爲字符串形式的來自服務器的完整響應
    • responseXML: Document對象,表示服務器的響應解析成的XML文檔
    • abort():取消異步HTTP請求
    • getAllResponseHeaders(): 返回一個字符串,包含響應中服務器發送的所有HTTP報頭。每一個報頭都是一個用冒號分隔開的名/值對,而且使用一個回車/換行來分隔報頭行
    • getResponseHeader(headerName):返回headName對應的報頭值
    • open(method, url, asynchronous [, user, password]):初始化準備發送到服務器上的請求。method是HTTP方法,不區分大小寫;url是請求發送的相對或絕對URL;asynchronous表示請求是否異步;user和password提供身份驗證
    • setRequestHeader(name, value):設置HTTP報頭
    • send(body):對服務器請求進行初始化。參數body包含請求的主體部分,對於POST請求爲鍵值對字符串;對於GET請求,爲null
  • 列舉數據相關的經常使用方法
    • push/pop,shift/unshift,slice/splice/concat,sort/recerse,map/reduce,forEach,filter。
  • 列舉字符串經常使用的方法
    • indexOf/lastIndexOf/charAt, split/match/test, slice/substring/substr, toLowerCase/toUpperCase
  • js裏的做用域是什麼樣子的?
    • js裏邊叫函數做用域,就是一個變量在全函數裏有效.好比有個變量p1在函數最後一行定義,第一行也有效,可是值是undefined.
    var globalVar = 'global var';
    
    function test() {
    alert(globalVar); // undefined, 由於globalVar在本函數內被重定義了,致使全局失效,這裏使用函數內的變量值,但是此時還沒定義
    var globalVar = 'overrided var'; //&emsp;globalVar在本函數內被重定義
    alert(globalVar);&emsp;// overrided var
    }
    alert(globalVar); // global var,使用全局變量
    複製代碼
  • 如何實現瀏覽器內多個標籤頁之間的通訊?
    • webSocket、loaclStorage、cookie、
  • 如何提升cookie的安全性?
    • httpOnly、cookie-secure的值改成true、超時設置。
  • 如何統計一個頁面加載時間?如何統計一個頁面首屏的加載時間?
  • 怎麼看koa跟express?
    • Koa更像架子,插件擴展;express是framework;Handler處理方式差別,一個是回調、一個是生成器函數
  • for ... in 和 for ... of 的區別?
    • for...in語句以原始插入順序迭代對象的可枚舉屬性。不完善,
    • for...of 可迭代對象定義要迭代的數據。 解決歷史問題。
  • setTimeout和Promise在異步實現上,有什麼區別?
    dd?
    複製代碼
  • 如何判斷一個變量是空對象?
    • Object.keys(ES6),for in循環
    • hasOwnProperty person.hasOwnProperty("name")
  • 箭頭函數=>的this是指向哪裏?
    • 箭頭函數不會建立本身的this,而是默認綁定函數的宿主對象(或者函數所綁定的對象等同類意思)
    • 若是有對象嵌套的狀況,則this綁定到最近的一層對象上。
  • 冒泡和捕獲,有什麼區別?有哪些事件是不會冒泡的?
    • focus、blur、load、unload等事件,不會冒泡。
  • 事件代理 or 委託(delegate)原理和做用是什麼?
    • 利用事件冒泡機制實現,做用是經過委託代理到父節點,解決子節點過多或者動態加載時的重複綁定問題
    • 實現原理:event.target監聽實際觸發元素;避免是指望元素的子節點,需追加parentNode循環判斷。
  • 知道哪些模塊化規範,你使用過哪些?
    • cmd:先下好,依賴就近,須要執行的時候再解析(seajs)
    • CommonJS: node使用的CommonJS
    • amd:(依賴前置,下載後當即解析) seajs 不多用了
    • es6 import Module :(編譯時加載,靜態加載,能夠實現靜態分析,優化加載);es6的模塊化;
    • export 導出時,有幾種寫法?他們之間區別是什麼?
      • export default和 export {a, b, c}
      • 前者 import 引入時,不須要關心導出的變量名,可是後者須要知道。
  • 瀏覽器的事件機制,包含了哪些階段?
    • 事件的三個階段(捕獲,目標源,冒泡)
  • 瀏覽器中的事件輪迴模型(Event Loop),什麼是微任務,什麼是宏任務?
    • 微任務包括 process.nextTick ,promise ,MutationObserver。
    • 宏任務包括 script , setTimeout ,setInterval ,setImmediate ,I/O ,UI rendering。
    • Event Loop 執行順序以下所示:
      • 首先執行同步代碼,這屬於宏任務
      • 當執行完全部同步代碼後,執行棧爲空,查詢是否有異步代碼須要執行
      • 執行全部微任務
      • 當執行完全部微任務後,若有必要會渲染頁面
      • 而後開始下一輪 Event Loop,執行宏任務中的異步代碼,也就是 setTimeout 中的回調函數
  • 瀏覽器有哪些緩存機制?
    • 緩存位置:Service Worker;Memory Cache(內存中的緩存);Disk Cache(硬盤中的緩存)
    • 緩存策略
      • 強緩存(經過設置兩種 HTTP Header 實現:Expires 和 Cache-Control 。強緩存表示在緩存期間不須要請求,state code 爲 200)
      • 協商緩存(緩存過時了,就須要發起請求驗證資源是否有更新。協商緩存能夠經過設置兩種 HTTP Header 實現:Last-Modified 和 ETag )
  • 瀏覽器渲染一個網頁的過程?
    • 1.瀏覽器接收到 HTML 文件並轉換爲 DOM 樹
    • 2.將 CSS 文件轉換爲 CSSOM 樹
    • 3.生成渲染樹
    • 注意點: 碰到script標籤會阻塞渲染,因此通常會把script放到頁腳。若是想要避免script阻塞頁面渲染,能夠給script標籤加 async或defer 屬性
  • 如何進行前端錯誤監控?
    • window.onerror方法能夠很好作前端錯誤監控
    window.onerror = function(message, url, line) {
        if (!url) return;
        var msg = {};
        //記錄客戶端環境
        msg.ua = window.navigator.userAgent;
        //只記錄message裏的message屬性就行了,
        //錯誤信息可能會比較晦澀,有些信息徹底無用,應酌情過濾
        msg.message = message.message;
        msg.url = url;
        msg.line = line;
        msg.page = window.location.href;
        var s = [];
        //將錯誤信息轉換成字符串
        for(var key in msg){
        s.push(key + '=' + msg[key]);
        }
        s = s.join('&');
        //這裏是用增長標籤的方法調用日誌收集接口,優勢是比較簡潔。
        new Image().src = '/ajax-jserror.php?' + encodeURIComponent(s) + '&t=' + Math.random();   
        };
    複製代碼
    • try&catch
  • 使用箭頭函數(arrow functions)的優勢是什麼?
    • 做用域安全:在箭頭函數以前,每個新建立的函數都有定義自身的 this 值(在構造函數中是新對象;在嚴格模式下,函數調用中的 this 是未定義的;若是函數被稱爲「對象方法」,則爲基礎對象等),但箭頭函數不會,它會使用封閉執行上下文的 this 值
    • 簡單:箭頭函數易於閱讀和書寫
    • 清晰:當一切都是一個箭頭函數,任何常規函數均可以當即用於定義做用域。開發者老是能夠查找 next-higher 函數語句,以查看 this 的值
  • 變量賦值
(() => {
  var a = b = 3;
})()
console.log(a) // a is not defined
console.log(b) // 3
// 等價於 b=3 && var a=b
// 因此console時,a不存在,b爲3
複製代碼
  • 數組去重的方法有哪些?
  • 防抖動和節流?
    • 防抖動就是:防抖動 Debouncing把觸發很是頻繁的事件(好比按鍵,滾動)合併成一次執行。基本思路是規定時間內僅僅觸發最後一次,依次類推,若是鏈接起來可能很長時間不會執行。先定義一個定時器,觸發一次判斷是否認時器是否已經賦值了,若是賦值了,清空定時器,從新賦值。
    • 其它解釋:任務頻繁觸發的狀況下,只有任務觸發的間隔超過指定間隔的時候,任務纔會執行
    function debounce(func, delay) {
              let timeOut = null; // 定義一個定時器函數;
              return function () {
                if(timeOut !== null){ // 若是已經賦值了,就清空定時器從新計算。
                  clearTimeout(timeOut);
                }
                timeOut = setTimeout(func,delay); //每次觸發就賦值,執行最後一次賦值的函數
              }
            }
        
            function handle() {
              console.log('抖動')
            }
        
            window.addEventListener('scroll',debounce(handle,500))
    複製代碼
    • 節流就是:固定時間內僅僅執行一次,若是從新賦值,從新計算。函數執行完,當即將定時器賦值爲空對象。用了apply改變this指向。
    • 其它解釋: 指定時間間隔內只會執行一次任務;
    // 應用場景:頁面resize 頁面scroll, input輸入效驗,搜索
    var throttle = function (func, delay) {
      let time = null;
      return function () {
        let _this = this;
        if(!time) { // 若是已經賦值就不要執行(賦值)了,
          time = setTimeout(function () {  // 經過賦值
            func.apply(_this, arguments); // func 參數
            time = null; // 約定時間執行完後 賦值爲null 新的生命週期開始
          }, delay)
        }
      }
    };
    function doSomfun(){
      console.log('節流',Math.random());
    };
    window.addEventListener('scroll',throttle(doSomfun, 1000))
    複製代碼
  • js實現千分位?
    function commafy(num) {
          return num && num
              .toString()
              .replace(/(\d)(?=(\d{3})+\.)/g, function($0, $1) {
                  return $1 + ",";
              });
      }
      console.log(commafy(1234567.90)); //1,234,567.90
    複製代碼
  • 怎麼讓 a == 1 && a == 2 && a == 3 的返回值爲 true ?
let a = {};
    let b = 1;
    a.valueOf = function () {
        console.log(b);
        return b++;
    }
    console.log(a == 1 && a == 2 && a == 3);

複製代碼
  • 能不能實現 a === 1 && a === 2 && a === 3 ?
let b = 1;
Object.defineProperty(window, 'a', {
    get() {
        console.log(b)
        return b++;
    }
})
console.log(a === 1 && a === 2 && a === 3);

複製代碼
  • 請問在js中,輸入表達式 0.1 + 0.2 的結果是什麼?
    • 0.30000000000000004(能回答出來不是0.3,而是0.3後有若干個0和一個數字便可)
    • 緣由是浮點數和整數,在存儲時的方法是不一樣的,所以相加的規則也是不一樣的;
    • 浮點數是怎麼存儲的?
  • 浮點數計算精度丟失問題?
    • // todo
  • 前端實現動畫的方式有哪些?
    • js:定時器改變 html 元素位置;
    • CSS3:transition 和 animation,區別有哪些?
      • 前者是針對屬性的,當屬性更改時,就會觸發動畫。使用起來更簡單
      • 後者是幀動畫,經過 keyframes 來設置幀狀態,從一幀過渡到另一幀,使用起來更強大。
    • canvas、SVG、WebGL
    • gif
    • flash
    • 參考
    • 當對動畫進行性能優化時,有哪些可使用的方案?
      • 儘可能減小DOM操做;
      • 對於複雜的流程展現型動畫,能夠考慮使用canvas;
      • 對於不方便使用js、css實現的動畫,使用gif替代;
  • 若是要進行錯誤捕獲,有哪些辦法?
    • try、catch;
    • window.onerror
    • promise的catch
  • 如何獲取選中的單選框的值?
    document.querySelectorAll("input[type='radio']").forEach(item => console.log(item.checked));  // 能夠拿取選中的那個。
    複製代碼
  • 寫一個函數實現從從路徑字符串中截取文件名的功能?
    /**
     * 從零字符串中讀取文件名.
     * @param  {String}filePath
     * @return {String}
     * @example
     *    getFileName('/user/document/abc.doc')  //=> abc.doc; 
     */
    function getFileName(filePath) {
      // 最笨實現
      // 可繼續追問的點:
      //     1. 是否能夠省去這個臨時數組?
      let pathList = filePath.split('/')[0];
      return pathList[ pathList.length - 1] || '';
      
      // 正則實現
      // 可繼續追問的點:
      //     1. 用正則如何判斷最後一級路徑?
      let match = /\/([^/]*)$/.match(filePath);
      return match && match[1] ? match[1] : '';
      
      // 最佳實現
      let posi =  filePath.lastIndexOf('/');
      return posi > -1 ? filePath.slice(posi + 1) : '';
    }
    複製代碼
  • 找出數組中出現次數超過一半的數字JavaScript
/* --------- 找出最接近的值 ----------- */
/* 儘可能不使用 JS 特有的語法糖,儘可能不使用如 Array.sort 等語言特有的方法。*/
const arr2 = [1, 5, 9, 15, 28, 33, 55, 78, 99];

/**
 * 返回最接近輸入值的數字,若是有多個,返回最大的那個
 * @param {number} n
 * @return {number}
 */
function findMoreThanHalf(arr) {
    // todo
}

// 測試用例
console.log(findMoreThanHalf([0])) // 0
console.log(findMoreThanHalf([0,1])) // -1
console.log(findMoreThanHalf([0,1,2,2])) // -1
console.log(findMoreThanHalf([0,1,2,2,2])) // 2
console.log(findMoreThanHalf([0,1,2,3,3,3])) // -1
console.log(findMoreThanHalf([0,1,2,3,3,3,3])) // 3
複製代碼
  • 數組洗牌
/* --------- 數組洗牌 ----------- */
/* 儘可能不使用 JS 特有的語法糖,儘可能不使用如 Array.sort 等語言特有的方法。*/
const arr = [3, 1, 22, 13, 5, 37, 42, 15, 5, 79, 38, 8, 28, 9];

/**
 * 不建立新的數組,返回原有數組,打亂裏面的數字順序,考慮性能,時間複雜度越低越好
 * @param {number[]} arr
 * @return {number[]}
 */
function shuffle(arr) {
  // todo
}
複製代碼
  • 如何拆解URL參數中queryString
const url = 'http://sample.com/?a=1&b=2&c=xx&d#hash';
/**
 * 返回 URL 參數中的 QueryString
 * @param url {string}
 * @return {Object}
 * @example
 * parseQueryString('http://sample.com/?a=1&b=2&c=xx&d&&==#hash')
 * -> { a: '1', b: '2', c: 'xx', d: '' };
 */
function parseQueryString(url) {
    // todo 
}
複製代碼
  • 用 DFS or BFS 來實現遍歷DOM樹
/**
     * 從頁面根節點開始,遍歷頁面上全部 DOM 元素,而且返回每一個DOM標籤的名稱和出現次數
     * 分別用「深度優先」和「廣度優先」的策略來實現
     * @param {HTMLElement} 頁面根節點
     * @return {Object} - 包含頁面上全部標籤名-該標籤出現次數的對象,eg: { div: 10, p: 20, h1: 3 }
     */
    function collectAllElements(e) {
        // your code here...
    }
複製代碼
  • 實現一個函數,能夠將數組轉化爲樹狀數據結構
// 入參格式參考:
    const arr = [
      { id: 1, name: 'i1' },
      { id: 2, name: 'i2', parentId: 1 },
      { id: 4, name: 'i4', parentId: 3 },
      { id: 3, name: 'i3', parentId: 2 },
      { id: 8, name: 'i8', parentId: 7 }
    ];
    
    /* 能夠將數組轉化爲樹狀數據結構,要求程序具備偵測錯誤輸入的能力*/
    function buildTree(arr) {
      /**
       * 此處寫代碼邏輯
       */
    }
複製代碼
  • 從 document 開始遍歷收集頁面中 DOM 樹上的全部元素,存放到數組中
/**
    分別用「深度優先」和「廣度優先」的策略來實現
    @param {HTMLElement} - e
    @return {HTMLElement[]}
    */
    function collectAllElements(e) {
    // your code here...
    }

複製代碼
  • 實現下面的find方法
var data = [
  { userId: 8, title: 'title1'},
  { userId: 11, title: 'other'},
  { userId: 15, title: null},
  { userId: 19, title: 'title2'}
];
var find = function(origin) {
  // your code here...
}
//查找data中,符合條件的數據,並進行排序
var result = find(data).where({
  "title": /\d$/
}).orderBy('userId', 'desc');
console.log(result); // [{ userId: 19, title: 'title2'}, { userId: 8, title: 'title1' }];

複製代碼
  • 實現一個簡單的模板引擎
var tpl = template('<p>hey there {{ name }}</p>');
var div = document.createElement('div');
div.innerHTML = tpl({ name: 'Neo' });
document.body.appendChild(div);
複製代碼
  • 實現一個AST解析方法,解析下列輸入,輸出對應樹形結構(區分標籤、屬性、內容等)
const htmlStr = `
    <div class="widget-body" data-spm-anchor-id="a1z4o.xxss.i3.14803e15bAFF41">
         <span class="ctr-val g-csscut-more" style="display: inline-block;vertical-align: top;width:200px;」><a target="_blank" href="positionDetail.htm?id=44106" title="歡迎應聘螞蟻金服支付寶前端工程師-杭州、上海、北京、成都">歡迎應聘螞蟻金服支付寶前端工程師-杭州、上海、北京、成都</a></span> </div>` function astParser(){ // todo } 複製代碼
  • 用原生js實現拖拽效果
<div id="container" style="border:1px solid red; position: absolute; width:100px; height: 100px">something</div>
 <script>
 //todo
 </script>
複製代碼
  • 實現自定義事件
// 2. 具有 off 方法解綁事件

function EventEmitter () {
  // TODO

}

var emitter = EventEmitter();

emitter.on('foo', function(e){
  console.log('listening foo event 1', e);
});

emitter.on('foo', function(e){
  console.log('listening foo event 2', e);
});

emitter.on('bar', function(e){
  console.log('listening bar event', e);
});
// 監聽所有事件
emitter.on('*', function(e){
  console.log('listening all events');
});
emitter.trigger('foo', {name : 'John'});
emitter.trigger('bar', {name : 'Sun'});
emitter.trigger('*', {name : 'Sun'});
emitter.off('foo');

複製代碼
  • 實現JS繼承
var Class = {};
    
    Class.create = function(props){
        // TODO
    };
    
    var Animal = Class.create({
        sleep : function(){
            console.log("zzzzzz~");
        }
    });
    
    var Person = Animal.extend({
        constructor : function(){
            this.type = "Person";
        },
        speak : function(){
            console.log("hello world!");
        }
    });
    
    var qitao = new Person("Qitao");
    qitao instanceof Person
    qitao instanceof Animal
複製代碼
  • 如何阻止事件冒泡?
    • ?
  • 常見測試題
var x = 1;
function ScopeTest(){
    alert( x ); // undefined
    var x = 'hello world';
    alert( x ); //hello world
}
ScopeTest();
複製代碼
// JS在執行每一段JS代碼以前, 都會首先處理var關鍵字和function定義式(函數定義式和函數表達式)
function test(xxx){
    alert(xxx); // function
    var xxx = 123;
    function xxx(){}
    alert(xxx); //123
}
test(444); //先彈出function而後123.
複製代碼
console.log(1);
setTimeout(function() {
console.log(2);
}, 0);
console.log(3);
// 132
複製代碼
var x = 1; 
 function ScopeTest(){
    alert( x );   // 1
}
複製代碼
var name = 'laruence';     
function echo()
 {         
  alert(name);   
 }      
function env()
 {
    var name = 'eve';         
    echo();   
}      

env(); // laruence
複製代碼
  • 若是你想要實現支持setter和getter特性的拷貝,該怎麼實現?javascript

    • Object.defineproperties (定義屬性) 和 Object.getOwnPropertyDescriptors(es2017,獲取對象的多個屬性)、Object.getOwnPropertyDescriptor(老一點,獲取對象的單個屬性的屬性),但babel能夠解決
  • 若是遍歷一個Object對象? for…in…, for…of… 的區別是什麼? forEach、map、filter、some、every函數的區別?php

    • //TODO
  • body中添加li標籤css

在一個body中插入十個<ul><li>第i項</li></ul>,考慮效率和性能
var str='<ul>'',$body; for(var i = 1;i<=10;i++){ str+='<li>第'+i+'項</li>' } str+='</ul>' $body=typeof document.querySelectorAll=='function'?document.querySelectorAll('body')[0]:document.getElementsByTagName('body')[0]; $body.innerHtml+=str; 複製代碼
  • 如何理解JavaScript原型鏈?、
    • JavaScript中的每一個對象都有一個prototype屬性,咱們稱之爲原型,而原型的值也是一個對象,所以它也有本身的原型,這樣就串聯起來了一條原型鏈,原型鏈的鏈頭是object,它的prototype比較特殊,值爲null。
    • 原型鏈的做用是用於對象繼承,函數A的原型屬性(prototype property)是一個對象,當這個函數被用做構造函數來建立實例時,該函數的原型屬性將被做爲原型賦值給全部對象實例,好比咱們新建一個數組,數組的方法便從數組的原型上繼承而來。、
    • 當訪問對象的一個屬性時, 首先查找對象自己, 找到則返回; 若未找到, 則繼續查找其原型對象的屬性(若是還找不到實際上還會沿着原型鏈向上查找, 直至到根). 只要沒有被覆蓋的話, 對象原型的屬性就能在全部的實例中找到,若整個原型鏈未找到則返回undefined
  • JavaScript的做用域和做用域鏈?
    • JavaScript的做用域指的是變量的做用範圍,內部做用域由函數的形參,實參,局部變量,函數構成,內部做用域和外部的做用域一層層的連接起來造成做用域鏈,當在在函數內部要訪問一個變量的時候,首先查找本身的內部做用域有沒有這個變量,若是沒有就到這個對象的原型對象中去查找,仍是沒有的話,就到該做用域所在的做用域中找,直到到window所在的做用域,每一個函數在聲明的時候就默認有一個外部做用域的存在了
    • 好比:bar找t變量的過程就是,先到本身的內部做用域中找,發現沒有找到,而後到bar所在的最近的外部變量中找,也就是foo的內部做用域,仍是沒有找到,再到window的做用域中找,結果找到了
    var t=4;
      function foo(){
        var tem=12;
          funciton bar(){
            var temo=34;
              console.log(t+" "+tem+" "+temo);
          }
      }
    複製代碼
  • setTimeout和Promise在異步實現上,有什麼區別?
    • todo?
  • 異步編程的實現方式?
    • 回調函數
      • 優勢:簡單、容易理解
      • 不利於維護,代碼耦合高
    • 事件監聽(採用時間驅動模式,取決於某個事件是否發生):
      • 優勢:容易理解,能夠綁定多個事件,每一個事件能夠指定多個回調函數
      • 缺點:事件驅動型,流程不夠清晰
    • 發佈/訂閱(觀察者模式)
      • 相似於事件監聽,可是能夠經過‘消息中心’,瞭解如今有多少發佈者,多少訂閱者
    • Promise對象
      • 優勢:能夠利用then方法,進行鏈式寫法;能夠書寫錯誤時的回調函數;
      • 缺點:編寫和理解,相對比較難
    • Generator函數
      • 優勢:函數體內外的數據交換、錯誤處理機制
      • 缺點:流程管理不方便
    • async函數
      • 優勢:內置執行器、更好的語義、更廣的適用性、返回的是Promise、結構清晰。
      • 缺點:錯誤處理機制
  • 解釋一下什麼是eventloop(事件循環)?
    • // todo
  • 若是要渲染一個10000行的table, 什麼辦法可以優化渲染?
    • 由於javascript是單線程,渲染10000行的數據會形成頁面主線程被hang住,致使頁面無響應,若是要渲染10000的數據能夠經過setTimeout將10000條數據分片渲染,防止主線程被hang住
  • new操做符具體能夠幹什麼呢?
    • 建立一個空對象,而且 this 變量引用該對象,同時還繼承了該函數的原型。
    • 屬性和方法被加入到 this 引用的對象中。
    • 新建立的對象由 this 所引用,而且最後隱式的返回 this 。
  • 如何清除字符串先後空格?
    • // todo
  • 工做中是如何設計後端 API 的?
    • http, 狀態碼,錯誤碼,json,restful,graphql
相關文章
相關標籤/搜索