為了提高公司內小伙伴的前端業務水平,每個月都有一個前端的測試,以下是第一期試題以及參考答案
恒星計劃第一期-前端考試
1. let const var 區別
var | let | const |
---|---|---|
函數級作用域 | 塊級作用域 | 塊級作用域 |
變量提升 | 不存在變量提升 | 不存在變量提升 |
值可更改 | 值可更改 | 值不可更改 |
- | 暫時性鎖區特性 | 如果變量是基本數據類型,不能更改值;如果是復雜數據類型,則不能更改內存地址。 |
2. js 中 this 的指向
this 的指向,是當我們調用函數的時候指定的,調用方式的不同,決定了 this 指向的不同
調用方式 | this 指向 |
---|---|
普通函數調用 | window |
定時器函數 | window |
立即執行函數 | window |
對象方法調用 | 該方法所屬的對象 |
事件綁定方法 | 綁定事件的對象 |
構造函數調用 | 實例對象,原型對象里面的方法也指向實例對象 |
3. call、apply、bind 的區別
- 不同點
- call 和 apply 會調用函數,并且改變函數內部 this 指向
- call 和 apply 傳遞的參數不一樣,前者傳遞參數使用逗號隔開,apply 使用數組傳遞
- bind 不會調用函數,但可以改變函數內部 this 指向
- 應用場景
- call 經常做繼承
- apply 經常跟數組有關,比如借助數學對象方法找出數組最大值最小值
- bind 方法執行后,返回的是原函數改變 this 指向之后的新函數,比如改變定時器內部 this 指向
3,js 中繼承各自有什么特點
-
原型鏈繼承
主要代碼
Child.prototype = new Parent()
-
特點
- 引用類型的屬性被所有實例共享
- 在創建子類實例時,不能向父類傳參
-
構造函數繼承
主要代碼
function Child() { Parent.call(this) }
-
特點
- 避免了引用類型的屬性被所有實例共享
- 可以在 Child 中向 Parent 傳參
- 方法都在構造函數中定義,每次創建實例都會創建一遍方法
-
組合繼承:以上兩種繼承的組合
主要代碼
function Child (name, age) { Parent.call(this, name) this.age = age } Child.prototype = new Parent() Child.prototype.constructor = Child
-
特點
- 融合原型鏈繼承和構造函數繼承的優點,是最常用的繼承模式
-
原型式繼承
主要代碼
function createObj(o){ function F() {} F.prototype = o; return new F() }
-
特點:
- 就是 Object.create 的模擬實現,將傳入對象作為創建對象的原型
- 包含引用類型的屬性值始終都會共享相應的值,類似原型鏈繼承
-
寄生組合式繼承
主要代碼
function Child (name, age) { Parent.call(this, name) this.age = age } Child.prototype = Object.create(Parent.prototype) Child.prototype.constructor = Child
-
特點:
- 比起組合繼承少調用一次 Parent 構造函數
- 引用類型最理想的繼承方式
4. new 關鍵字的作用
- 在內存中創建一個新對象
- 該新對象會被鏈接到原型鏈上
- 把 this 指向創建出來的空對象,并執行構造函數中的代碼
- 如果函數沒有返回其它對象,則返回這個新對象
5. js中創建對象的方式
- 使用 new Object 創建對象
- 使用對象字面量創建對象
- 使用構造函數創建對象
6. ES6怎么定義類,以及實現類的繼承
- 通過class關鍵字創建類
class Animal {}
- 通過 extends 關鍵字實現繼承
class Dog extends Animal{}
7. JS中對象訪問規則
- 通過 . 方式訪問,如: obj.a
- 通過中括號的方式訪問,如:obj['hello-world']
8. JS中構造函數和Object的原型鏈搜索機制
- 先從對象自身查找,找到則直接訪問,結束查找
- 如果找不到則沿著原型鏈依次往上查找,找到則直接訪問
- 如果最終來到原型鏈頂端,Object.prototye 還是沒有找到的話則直接返回 undefined
9. 構造函數和普通函數的區別
- 本質上來說構造函數和普通函數沒有任何區別
- 它們只有調用方式的不同,構造函數通過new操作符調用的時候會返回一個新對象
10. promise 主要解決了什么問題,如何一直 .then 下去
- 主要解決了無限嵌套回調地獄的問題
- promise 實例擁有的then方法,而then方法返回的結果也會被js包裝成promise實例,所以能夠一直 .then 下去
11. ES6 怎么實現數組去重
- Array.from(new Set(arr))
12. ES6中字符串新增了哪些方法
模板字符串
padStart, padEnd
startsWith, endsWith
includes
repeat
13. 代碼實現數組從小到大排序,至少兩種方式
var arr = [1,2,1,3,4] for (let i = 0; i < arr.length; i++){ for (let j = i; j < arr.length; j++){ if (arr[i] > arr[j]) { var max = arr[i] arr[i] = arr[j] arr[j] = max } } } console.log(arr)
var arr = [1,3,2,-1] var newArr = [] for (;arr.length>0;) { var min = Math.min.apply(null, arr) newArr.push(min) var index = arr.findIndex(x => x === min) arr.splice(index, 1) } console.log(newArr)
arr.sort((a, b) => a - b)
14. 使用 proxy 實現觀察者模式
觀察者模式是行為模式之一,它的作用是當一個對象的狀態發生變化時,能夠自動通知其他關聯對象,自動刷新對象狀態。
const callbacks = new Set();
const observe = fn => callbacks.add(fn)
const observable = obj => new Proxy(obj, {set})
function set(target, key, value, receiver) {
const result = Reflect.set(target, key, value, receiver);
callbacks.forEach(observe => observe());
return result;
}
// 一個可觀察的對象
const person = observable({name: 'hui', age: 22})
function change() {
console.log(`${person.name} is ${person.age}`)
}
observe(change)
pserson.age = 33