前端面試筆記 – js相關

cppprimer發表於2019-02-16

請解釋事件代理 (event delegation)。

將單個事件繫結在父物件上,利用冒泡機制,監聽來自子元素的事件。

優點:解決子元素增加刪除時候的事件處理,防止記憶體洩漏

事件捕獲:當某個元素觸發某個事件(如onclick),頂層物件document就會發出一個事件流,隨著DOM樹的節點向目標元素節點流去,直到到達事件真正發生的目標元素。在這個過程中,事件相應的監聽函式是不會被觸發的。

事件目標:當到達目標元素之後,執行目標元素該事件相應的處理函式。如果沒有繫結監聽函式,那就不執行。

事件起泡:從目標元素開始,往頂層元素傳播。途中如果有節點繫結了相應的事件處理函式,這些函式都會被一次觸發。如果想阻止事件起泡,可以使用e.stopPropagation()(Firefox)或者e.cancelBubble=true(IE)來組織事件的冒泡傳播。

請解釋 JavaScript 中 this 是如何工作的。

stackoverflow

  • 在全域性環境時
// this 表示window

function f(){
    return this //也是window
}
  • 放在object方法裡面時

this繫結到包含他的物件

var obj = {
    name: "obj",
    f: function () {
        return this + ":" + this.name;
    }
};
document.write(obj.f());
var obj = {
    name: "obj1",
    nestedobj: {
        name:"nestedobj",
        f: function () {
            return this + ":" + this.name;
        }
    }            
}

document.write(obj.nestedobj.f()); //[object Object]:nestedobj

即使你隱式的新增方法到物件,this仍然指向
立即父物件

var obj1 = {
    name: "obj1",
}

function returnName() {
    return this + ":" + this.name;
}

obj1.f = returnName; //add method to object
document.write(obj1.f()); //[object Object]:obj1
  • 當呼叫一個無上下問的函式

當函式呼叫沒有包含上下文,this將繫結到global物件

var context = "global";

var obj = {  
    context: "object",
    method: function () {                  
        function f() {
            var context = "function";
            return this + ":" +this.context; 
        };
        return f(); //invoked without context
    }
};

document.write(obj.method()); //[object Window]:global 
  • 當使用在建構函式時

即使用new關鍵字時,this指向剛建立的物件

var myname = "global context";
function SimpleFun()
{
    this.myname = "simple function";
}

var obj1 = new SimpleFun(); //adds myname to obj1
//1. `new` causes `this` inside the SimpleFun() to point to the
//   object being constructed thus adding any member
//   created inside SimipleFun() using this.membername to the
//   object being constructed
//2. And by default `new` makes function to return newly 
//   constructed object if no explicit return value is specified

document.write(obj1.myname); //simple function
  • 當內部物件定義在原型鏈時

當一個方法定義在物件原型鏈,this指向呼叫該方法的物件

var ProtoObj = {
    fun: function () {
        return this.a;
    }
};
//Object.create() creates object with ProtoObj as its
//prototype and assigns it to obj3, thus making fun() 
//to be the method on its prototype chain

var obj3 = Object.create(ProtoObj);
obj3.a = 999;
document.write(obj3.fun()); //999

//Notice that fun() is defined on obj3`s prototype but 
//`this.a` inside fun() retrieves obj3.a   
  • 在 call(), apply() and bind() 函式內部
fun.apply(obj1 [, argsArray])
fun.call(obj1 [, arg1 [, arg2 [,arg3 [, ...]]]]) 
設定this函式並執行
fun.bind(obj1 [, arg1 [, arg2 [,arg3 [, ...]]]])
設定this
  • this在事件處理上

如果函式在eventHandler和onclick直接被呼叫 this指向元素(currentTarget)
否則執行window

<script> 
    function clickedMe() {
       alert(this + " : " + this.tagName + " : " + this.id);
    } 
    document.getElementById("button1").addEventListener("click", clickedMe, false);
    document.getElementById("button2").onclick = clickedMe;
    document.getElementById("button5").attachEvent(`onclick`, clickedMe);   
</script>

<h3>Using `this` "directly" inside event handler or event property</h3>
<button id="button1">click() "assigned" using addEventListner() </button><br />
<button id="button2">click() "assigned" using click() </button><br />
<button id="button3" onclick="alert(this+ ` : ` + this.tagName + ` : ` + this.id);">used `this` directly in click event property</button>

<h3>Using `this` "indirectly" inside event handler or event property</h3>
<button onclick="alert((function(){return this + ` : ` + this.tagName + ` : ` + this.id;})());">`this` used indirectly, inside function <br /> defined & called inside event property</button><br />

<button id="button4" onclick="clickedMe()">`this` used indirectly, inside function <br /> called inside event property</button> <br />

IE only: <button id="button5">click() "attached" using attachEvent() </button>

請解釋原型繼承 (prototypal inheritance) 的原理。

當定義一個函式物件的時候,會包含一個預定義的屬性,叫prototype,這就屬性稱之為原型物件。

function F(){};
console.log(F.prototype)
//F.prototype包含
//contructor建構函式

JavaScript在建立物件的時候,都會有一個[[proto]]的內建屬性,用於指向建立它的函式物件的prototype。原型物件也有[[proto]]屬性。因此在不斷的指向中,形成了原型鏈。

//函式物件
function F(){};
F.prototype = {
    hello : function(){}
};
var f = new F();
console.log(f.__proto__)

當使用new去呼叫建構函式時,相當於執行了

var o = {};
o.__proto__ = F.prototype;
F.call(o);

原型物件prototype上都有個預定義的constructor屬性,用來引用它的函式物件。這是一種迴圈引用。

function F(){};
F.prototype.constructor === F;
( new Foo ).__proto__ === Foo.prototype
( new Foo ).prototype === undefined

__proto__真正的原型鏈
prototype只存在與建構函式中

你怎麼看 AMD vs. CommonJS?

請解釋為什麼接下來這段程式碼不是 IIFE (立即呼叫的函式表示式):function foo(){ }();.

沒有加括號

要做哪些改動使它變成 IIFE?

描述以下變數的區別:null,undefined 或 undeclared?

該如何檢測它們?

null===null
undefined === undefined

什麼是閉包 (closure),如何使用它,為什麼要使用它?

函式閉包(function closures),是引用了自由變數的函式。這個被引用的自由變數將和這個函式一同存在,即使已經離開了創造它的環境也不例外

請舉出一個匿名函式的典型用例?

回撥

你是如何組織自己的程式碼?是使用模組模式,還是使用經典繼承的方法?

請指出 JavaScript 宿主物件 (host objects) 和原生物件 (native objects) 的區別?

請指出以下程式碼的區別:function Person(){}、var person = Person()、var person = new Person()?

.call 和 .apply 的區別是什麼?

apply 第二個引數是陣列
call 第二個以後的可變引數

請解釋 Function.prototype.bind?

在什麼時候你會使用 document.write()?

寫script

請指出瀏覽器特性檢測,特性推斷和瀏覽器 UA 字串嗅探的區別?

請儘可能詳盡的解釋 Ajax 的工作原理。

XMLHttpRequest

使用 Ajax 都有哪些優劣?

請解釋 JSONP 的工作原理,以及它為什麼不是真正的 Ajax。

通過在網頁中加入script標籤,是瀏覽器通過get方式載入一段js程式碼

你使用過 JavaScript 模板系統嗎?

如有使用過,請談談你都使用過哪些庫?

請解釋變數宣告提升 (hoisting)。

通過 var 宣告的變數在程式碼執行之前被js引擎提升到了當前作用域的頂部

請描述事件冒泡機制 (event bubbling)。

一個事件被觸發,會發生先捕獲後冒泡的行為。
冒泡機制指一個事件從發生元素開始先父元素傳遞,直到達到根元素

“attribute” 和 “property” 的區別是什麼?

js dom 物件擁有的property,property有很多型別
attribute是指html擁有的特性,型別是字串

為什麼擴充套件 JavaScript 內建物件不是好的做法?

請指出 document load 和 document DOMContentLoaded 兩個事件的區別。

DomContentLoaded事件發生在domcument物件被初始化完成,css,圖片和frame還沒被載入的時候

load事件表示資源被全部載入

== 和 === 有什麼不同?

==會發生型別轉換
===不會發生型別轉換

請解釋 JavaScript 的同源策略 (same-origin policy)。

同源策略限制從一個源載入的文件或指令碼如何與來自另一個源的資源進行互動

http://store.company.com/dir2… 成功
http://store.company.com/dir/… 成功
https://store.company.com/sec… 失敗 不同協議 ( https和http )
http://store.company.com:81/dir/etc.html 失敗 不同埠 ( 81和80)
http://news.company.com/dir/o… 失敗 不同域名 ( news和store

如何實現下列程式碼:

[1,2,3,4,5].duplicator(); // [1,2,3,4,5,1,2,3,4,5]
Arrry.prototype.duplicator = function(){
    return this.concat(this)
}

什麼是三元表示式 (Ternary expression)?“三元 (Ternary)” 表示什麼意思?

什麼是 “use strict”; ? 使用它的好處和壞處分別是什麼?

“use strict” 告訴js執行時以嚴格模式執行javascript語句
使js以更安全的方式執行,對某些行為直接報錯

請實現一個遍歷至 100 的 for loop 迴圈,在能被 3 整除時輸出 “fizz”,在能被 5 整除時輸出 “buzz”,在能同時被 3 和 5 整除時輸出 “fizzbuzz”。

for(let i=1;i<=100;i++){
    let word = ""
    if(i % 3 ==0){
        word += "fizz"
    }
    if(i % 5 ==0){
        word += "buzz"
    }
    if(word){
        console.log(word)
    }
}

為何通常會認為保留網站現有的全域性作用域 (global scope) 不去改變它,是較好的選擇?

為何你會使用 load 之類的事件 (event)?此事件有缺點嗎?你是否知道其他替代品,以及為何使用它們?

請解釋什麼是單頁應用 (single page app), 以及如何使其對搜尋引擎友好 (SEO-friendly)。

單頁應用是指所有的資源互動都放在一個頁面,而不是互動的時候跳轉到另一個頁面。
使用ssr服務端渲染。

你使用過 Promises 及其 polyfills 嗎? 請寫出 Promise 的基本用法(ES6)。

new Promise(resolve,reject)
Promise.resolve
Promise.reject

使用 Promises 而非回撥 (callbacks) 優缺點是什麼?

將回撥轉換成鏈式呼叫

使用一種可以編譯成 JavaScript 的語言來寫 JavaScript 程式碼有哪些優缺點?

你使用哪些工具和技術來除錯 JavaScript 程式碼?

console.log
debuger

你會使用怎樣的語言結構來遍歷物件屬性 (object properties) 和陣列內容?

array array.foreach
object for var i in xx i是字串

請解釋可變 (mutable) 和不變 (immutable) 物件的區別。

mutable
imuutable表示物件建立後就不再變化

請舉出 JavaScript 中一個不變性物件 (immutable object) 的例子?

不變性 (immutability) 有哪些優缺點?

可以比較物件,執行緒安全
缺點就是費記憶體

如何用你自己的程式碼來實現不變性 (immutability)?

請解釋同步 (synchronous) 和非同步 (asynchronous) 函式的區別。

同步是指順序執行,會有阻塞
非同步是指函式立即執行並返回

什麼是事件迴圈 (event loop)?

主執行緒執行的時候,產生堆(heap)和棧(stack),棧中的程式碼呼叫各種外部API,它們在”任務佇列”中加入各種事件(click,load,done)。只要棧中的程式碼執行完畢,主執行緒就會去讀取”任務佇列”,依次執行那些事件所對應的回撥函式。

請問呼叫棧 (call stack) 和任務佇列 (task queue) 的區別是什麼?

javascript中的所有任務分為兩類,
一類是同步任務,另一種是一部任務。
所有的同步任務都在主執行緒上執行,
當同步任務執行完在執行非同步任務。

call stack 指主線執行緒執行任務的地方,當呼叫棧為空的時候,
會去輪詢task queue,然後將佇列裡的任務加入棧中執行
tast queue 按照包含一系列任務的佇列

解釋 function foo() {} 與 var foo = function() {} 用法的區別

第一個表示生成一個命名的函式
第二個表示生成一個匿名函式 ,並賦值給foo

What are the differences between variables created using let, var or const?

let var const都表示申明一個變數

var的作用於是函式體的全部,會發生作用於提升
let,const是塊級作用域
let表示可以被多次賦值
const表示只能被一次賦值

{} + {}

js的加法只有兩種

  1. 字串和字串的相加
  2. 數字和數字的相加

加法運算會觸發三種轉換

  1. 原始值
  2. 數字
  3. 字串
> [] + []
``
//[].toString()為空字串,空字串相加

> [] + {}
`[object Object]`

> {} + {}
`NaN` 
// 火狐下為NaN 因為第一個物件當作空程式碼塊,實際執行為 +{}

相關文章