去面試啦JS

JavaScript 的組成

ES,DOM,BOMjavascript

 

轉Boolean

在條件判斷時,除了 undefined, null, false, NaN, '', 0, -0,其餘全部值都轉爲 true,包括全部對象。css

#對象轉基本類型

對象在轉換基本類型時,首先會調用 valueOf 而後調用 toStringjava

 

JS 的基本數據類型和引用數據類型

基本:null,underfined,number,string,symbol,booleanajax

引用:Array,Object,Functionexpress

 

檢測瀏覽器版本版本有哪些方式?

  • 根據 navigator.userAgent
  • 根據 window 對象的成員 // 'ActiveXObject' in window

介紹 JS 有哪些內置對象?

  • 數據封裝類對象:Object、Array、Boolean、Number、String
  • 其餘對象:Function、Arguments、Math、Date、RegExp、Error
  • ES6 新增對象:Symbol、Map、Set、Promises、Proxy、Reflect

 

如何編寫高性能的 JavaScript?

  • 遵循嚴格模式:"use strict";
  • 將 js 腳本放在頁面底部,加快渲染頁面
  • 將 js 腳本將腳本成組打包,減小請求
  • 儘可能使用局部變量來保存全局變量
  • 儘可能減小使用閉包
  • 緩存 DOM 節點的訪問
  • 給 setTimeout() 和 setInterval() 傳遞函數而不是字符串做爲參數
  • 最小化重繪(repaint)和迴流(reflow)

 

offsetWidth/offsetHeight,clientWidth/clientHeight 與 scrollWidth/scrollHeight 的區別

  • offsetWidth/offsetHeight 返回值包含 content + padding + border,效果與 e.getBoundingClientRect()相同
  • clientWidth/clientHeight 返回值只包含 content + padding,若是有滾動條,也不包含滾動條
  • scrollWidth/scrollHeight 返回值包含 content + padding + 溢出內容的尺寸

描述瀏覽器的渲染過程

  • 解析 HTML 構建 DOM(DOM 樹),並行請求 css/image/js
  • CSS 文件下載完成,開始構建 CSSOM(CSS 樹)
  • CSSOM 構建結束後,和 DOM 一塊兒生成 Render Tree(渲染樹)
  • 佈局(Layout):計算出每一個節點在屏幕中的位置
  • 顯示(Painting):經過顯卡把頁面畫到屏幕上

DOM 樹 和 渲染樹 的區別:設計模式

  • DOM 樹與 HTML 標籤一一對應,包括 head 和隱藏元素
  • 渲染樹不包括 head 和隱藏元素,每個節點都有對應的 css 屬性

重繪和迴流(重排)的區別和關係?

  • 重繪:當渲染樹中的元素外觀(如:顏色)發生改變,不影響佈局時,產生重繪
  • 迴流:當渲染樹中的元素的佈局(如:尺寸、位置、隱藏/狀態狀態)發生改變時,產生重繪迴流
  • 注意:JS 獲取 Layout 屬性值(如:offsetLeft、scrollTop、getComputedStyle 等)也會引發迴流。由於瀏覽器須要經過迴流計算最新值
  • 迴流必將引發重繪,而重繪不必定會引發迴流

如何最小化重繪(repaint)和迴流(reflow)?

  • 須要要對元素進行復雜的操做時,能夠先隱藏(display:"none"),操做完成後再顯示
  • 須要建立多個 DOM 節點時,使用 DocumentFragment 建立完後一次性的加入 document
  • 緩存 Layout 屬性值,如:var left = elem.offsetLeft; 這樣,屢次使用 left 只產生一次迴流
  • 儘可能避免用 table 佈局(table 元素一旦觸發迴流就會致使 table 裏全部的其它元素迴流)
  • 避免使用 css 表達式(expression),由於每次調用都會從新計算值(包括加載頁面)
  • 儘可能使用 css 屬性簡寫,如:用 border 代替 border-width, border-style, border-color 批量修改元素樣式:elem.className 和 elem.style.cssText 代替 elem.style.xxx

 

script 的位置是否會影響首屏顯示時間?

  • 瀏覽器解析 HTML 是自上而下的線性過程,script 做爲 HTML 的一部分一樣遵循這個原則
  • 所以,script 會延遲 DomContentLoad,只顯示其上部分首屏內容,從而影響首屏顯示的完成時間

解釋 JavaScript 中的做用域與變量聲明提高?

Js中做用域是函數做用域,瀏覽器

函數聲明與變量聲明常常被 JavaScript 引擎隱式地提高到當前做用域的頂部。緩存

函數聲明的優先級高於變量安全

 

JavaScript 的原型,原型鏈?

原型鏈:多線程

  • 當一個對象調用的屬性/方法自身不存在時,就會去本身 [proto] 關聯的前輩 prototype 對象上去找
  • 若是沒找到,就會去該 prototype 原型 [proto] 關聯的前輩 prototype 去找。依次類推,直到找到屬性/方法或 undefined 爲止。從而造成了所謂的「原型鏈」

原型特色:

  • JavaScript 對象是經過引用來傳遞的,當修改原型時,與之相關的對象也會繼承這一改變

 

JavaScript 如何實現一個類,怎麼實例化這個類?

1.new

2.Object.create

3.class

javascript 建立對象的幾種方式?

  1. 對象字面量的方式
  2. 構造函數
  3. 工廠模式
  4. 混合方式

Javascript 如何實現繼承?

  1. 構造函數綁定:使用 call 或 apply 方法,將父對象的構造函數綁定在子對象上
  2. 實例繼承:將子對象的 prototype 指向父對象的一個實例
  3. 拷貝繼承:若是把父對象的全部屬性和方法,拷貝進子對象
  4. 原型繼承:將子對象的 prototype 指向父對象的 prototype
  5. ES6 語法糖 extends:class ColorPoint extends Point {}

js 繼承方式及其優缺點

原型鏈繼承的缺點

  • 一是字面量重寫原型會中斷關係,使用引用類型的原型,而且子類型還沒法給超類型傳遞參數。

借用構造函數(類式繼承)

  • 借用構造函數雖然解決了剛纔兩種問題,但沒有原型,則複用無從談起。因此咱們須要原型鏈+借用構造函數的模式,這種模式稱爲組合繼承

組合式繼承

  • 組合式繼承是比較經常使用的一種繼承方法,其背後的思路是使用原型鏈實現對原型屬性和方法的繼承,而經過借用構造函數來實現對實例屬性的繼承。這樣,既經過在原型上定義方法實現了函數複用,又保證每一個實例都有它本身的屬性。

 

Javascript 做用鏈域?

  • 若是當前做用域沒有找到屬性或方法,會向上層做用域查找,直至全局函數,這種形式就是做用域鏈

在一個 DOM 上同時綁定兩個點擊事件:一個用捕獲,一個用冒泡。事件會執行幾回,先執行冒泡仍是捕獲?

  • 該 DOM 上的事件若是被觸發,會執行兩次(執行次數等於綁定次數)
  • 若是該 DOM 是目標元素,則按事件綁定順序執行,不區分冒泡/捕獲
  • 若是該 DOM 是處於事件流中的非目標元素,則先執行捕獲,後執行冒泡

談談 this 對象的理解

  • this 老是指向函數的直接調用者

1.是否在new中調用,this=>新建立的對象

2.時候經過apply,call或者硬綁定,this=>指定對象

3.時候有某個上下文對象中調用obj.foo(),this=>obj

4.this=>window(underfined)

 

事件的代理/委託

事件委託是指將事件綁定目標元素的到父元素上,利用冒泡機制觸發該事件

優勢:

  • 能夠減小事件註冊,節省大量內存佔用
  • 能夠將事件應用於動態添加的子元素上

 

如何派發事件(dispatchEvent)?(如何進行事件廣播?)

  • W3C: 使用 dispatchEvent 方法
  • IE: 使用 fireEvent 方法
var fireEvent = function(element, event){ if (document.createEventObject){ var mockEvent = document.createEventObject(); return element.fireEvent('on' + event, mockEvent) }else{ var mockEvent = document.createEvent('HTMLEvents'); mockEvent.initEvent(event, true, true); return !element.dispatchEvent(mockEvent); } }


什麼是函數節流?介紹一下應用場景和原理?

  • 函數節流(throttle)是指阻止一個函數在很短期間隔內連續調用。 只有當上一次函數執行後達到規定的時間間隔,才能進行下一次調用。 但要保證一個累計最小調用間隔(不然拖拽類的節流都將無連續效果)
  • 函數節流用於 onresize, onscroll 等短期內會屢次觸發的事件
  • 函數節流的原理:使用定時器作時間節流。 當觸發一個事件時,先用 setTimout 讓這個事件延遲一小段時間再執行。 若是在這個時間間隔內又觸發了事件,就 clearTimeout 原來的定時器, 再 setTimeout 一個新的定時器重複以上流程。

函數節流簡單實現:

function throttle(method, context) { clearTimeout(methor.tId); method.tId = setTimeout(function(){ method.call(context); }, 100); // 兩次調用至少間隔 100ms } // 調用 window.onresize = function(){ throttle(myFunc, window); }



區分什麼是「客戶區座標」、「頁面座標」、「屏幕座標」?

  • 客戶區座標:鼠標指針在可視區中的水平座標(clientX)和垂直座標(clientY)
  • 頁面座標:鼠標指針在頁面佈局中的水平座標(pageX)和垂直座標(pageY)
  • 屏幕座標:設備物理屏幕的水平座標(screenX)和垂直座標(screenY)

如何得到一個 DOM 元素的絕對位置?

  • elem.offsetLeft:返回元素相對於其定位父級左側的距離
  • elem.offsetTop:返回元素相對於其定位父級頂部的距離
  • elem.getBoundingClientRect():返回一個 DOMRect 對象,包含一組描述邊框的只讀屬性,單位像素

new 操做符具體幹了什麼?

1.創造一個全新的對象

2.這個新對象會被執行[[Prototype]]鏈接

3.這個新對象會綁定到函數調用的this

4.若是函數沒有返回其餘對象,自動返回這個新對象

new會改變硬綁定函數的this,使用new硬綁定函數主要是爲了預先設置函數的一些參數

 

function create() {
    // 建立一個空的對象
    let obj = new Object()
    // 得到構造函數
    let Con = [].shift.call(arguments)
    // 連接到原型
    obj.__proto__ = Con.prototype
    // 綁定 this,執行構造函數
    let result = Con.apply(obj, arguments)
    // 確保 new 出來的是個對象
    return typeof result === 'object' ? result : obj
}

  

什麼是閉包(closure),爲何要用它?

閉包是指有權訪問另外一個函數做用域中變量的函數,建立閉包的最多見的方式就是在一個函數內建立另外一個函數,經過另外一個函數訪問這個函數的局部變量,利用閉包能夠突破做用鏈域

閉包的特性:

  • 函數內再嵌套函數
  • 內部函數能夠引用外層的參數和變量
  • 參數和變量不會被垃圾回收機制回收

用過哪些設計模式?

  1. 工廠模式:
  • 主要好處就是能夠消除對象間的耦合,經過使用工程方法而不是 new 關鍵字。將全部實例化的代碼集中在一個位置防止代碼重複
  • 工廠模式解決了重複實例化的問題 ,但還有一個問題,那就是識別問題,由於根本沒法 搞清楚他們究竟是哪一個對象的實例
  1. 構造函數模式

請解釋一下 JavaScript 的同源策略

這裏的同源策略指的是:協議,域名,端口相同,同源策略是一種安全協議

 

實現一個函數 clone,能夠對 JavaScript 中的 5 種主要的數據類型(包括 Number、String、Object、Array、Boolean)進行值複製(常考)

function deepClone(obj) { if (!isObject(obj)) { throw new Error('obj 不是一個對象!') } let isArray = Array.isArray(obj) let cloneObj = isArray ? [] : {} for (let key in obj) { cloneObj[key] = isObject(obj[key]) ? deepClone(obj[key]) : obj[key] } return cloneObj }


哪些操做會形成內存泄漏?

  • JavaScript 內存泄露指對象在不須要使用它時仍然存在,致使佔用的內存不能使用或回收
  • 未使用 var 聲明的全局變量
  • 閉包函數(Closures)
  • 循環引用(兩個對象相互引用)
  • 控制檯日誌(console.log)
  • 移除存在綁定事件的 DOM 元素(IE)

爲何 JS 是單線程,而不是多線程 [常考]

  • 單線程是指 JavaScript 在執行的時候,有且只有一個主線程來處理全部的任務。
  • 目的是爲了實現與瀏覽器交互。
  • 咱們設想一下,若是 JavaScript 是多線程的,如今咱們在瀏覽器中同時操做一個 DOM,一個線程要求瀏覽器在這個 DOM 中添加節點,而另外一個線程卻要求瀏覽器刪掉這個 DOM 節點,那這個時候瀏覽器就會很鬱悶,他不知道應該以哪一個線程爲準。因此爲了不此類現象的發生,下降複雜度,JavaScript 選擇只用一個主線程來執行代碼,以此來保證程序執行的一致性。

瀏覽器中的 Event Loop

 

  • 主線程運行的時候會生成堆(heap)和棧(stack);
  • js 從上到下解析方法,將其中的同步任務按照執行順序排列到執行棧中;
  • 當程序調用外部的 API 時,好比 ajax、setTimeout 等,會將此類異步任務掛起,繼續執行執行棧中的任務,等異步任務返回結果後,再按照執行順序排列到事件隊列中;
  • 主線程先將執行棧中的同步任務清空,而後檢查事件隊列中是否有任務,若是有,就將第一個事件對應的回調推到執行棧中執行,若在執行過程當中遇到異步任務,則繼續將這個異步任務排列到事件隊列中。
  • 主線程每次將執行棧清空後,就去事件隊列中檢查是否有任務,若是有,就每次取出一個推到執行棧中執行,這個過程是循環往復的... ...,這個過程被稱爲「Event Loop 事件循環」
相關文章
相關標籤/搜索