js經典試題之ES6
1:在ECMAScript6 中,Promise的狀態
答案:pending resolved(fulfilled) rejected
解析:
Promise對象只有三種狀態:
異步操作“未完成”(pending)—— 異步操作“已完成”(resolved,又稱fulfilled)—— 異步操作“失敗”(rejected)
這三種的狀態的變化途徑只有兩種:
異步操作從“未完成”到“已完成”——異步操作從“未完成”到“失敗”。
這種變化只能發生一次,一旦當前狀態變為“已完成”或“失敗”,就意味着不會再有新的狀態變化了。因此,Promise對象的最終結果只有兩種:
異步操作成功,Promise對象傳回一個值,狀態變為resolved。——異步操作失敗,Promise對象拋出一個錯誤,狀態變為rejected。
2:以下符合 ES6 寫法的有:
class Foo { constructor() {return Object.create(null);} } Foo()
var m=1; export m;
export var firstName=’Michael’;
在A模塊中export{readFile}后,在B模塊中import readFile from ‘A’可以獲取到readFile
答案: C
解析:
export {name1,name2, …,nameN}; export {variable1asname1,variable2asname2, …,nameN}; export letname1,name2, …,nameN; // also var export letname1= …,name2= …, …,nameN; // also var, const
export expression; export default expression; export default function (…) { … } // also class, function* export default function name1(…) { … } // also class, function* export {name1as default, … };
export * from …; export {name1,name2, …,nameN} from …; export {import1asname1,import2asname2, …,nameN} from …;
import defaultMember from "module-name"; import * as name from "module-name"; import { member } from "module-name"; import { member as alias } from "module-name"; import { member1 , member2 } from "module-name"; import { member1 , member2 as alias2 , [...] } from "module-name"; import defaultMember, { member [ , [...] ] } from "module-name"; import defaultMember, * as name from "module-name"; import "module-name";
3:以下代碼的輸出結果
setTimeout(function(){console.log(4)},0); new Promise(function(resolve){ console.log(1) for( var i=0 ; i<10000 ; i++ ){ i==9999 && resolve() } console.log(2) }).then(function(){ console.log(5) }); console.log(3);
答案: 1 2 3 5 4
解析:因為 setTimeout 是屬於 macrotask 的,而整個 script 也是屬於一個 macrotask, promise.then 回調 是 microtask ,執行過程大概如下:
- 由於整個 script 也屬於一個 macrotask, 由於會先執行 macrotask 中的第一個任務,再加上promise 構造函數因為是同步的,所以會先打印出 1和2
- 然后繼續同步執行末尾的 console.log(3) 打印出3
- 此時 setTimeout 被推進到 macrotask 隊列中, promise.then 回調被推進到 microtask 隊列中
- 由於在第一步中已經執行完了第一個 macrotask , 所以接下來會順序執行所有的 microtask, 也就是 promise.then 的回調函數,從而打印出5
- microtask 隊列中的任務已經執行完畢,繼續執行剩下的 macrotask 隊列中的任務,也就是 setTimeout, 所以打印出 4
macrotasks: setTimeout setInterval setImmediate I/O UI渲染
microtasks: Promise process.nextTick Object.observe MutationObserver
4、關於 javascript 模塊化,AMD和CMD的含義和區別
AMD是"Asynchronous Module Definition"的縮寫,意思就是"異步模塊定義"。它采用異步方式加載模塊,模塊的加載不影響它后面語句的運行。所有依賴這個模塊的語句,都定義在一個回調函數中,等到加載完成之后,這個回調函數才會運行。
AMD也采用require()語句加載模塊,但是不同於CommonJS。
主要有兩個Javascript庫實現了AMD規范:require.js和curl.js。
AMD 是 RequireJS 在推廣過程中對模塊定義的規范化產出。
CMD 是 SeaJS 在推廣過程中對模塊定義的規范化產出。
區別:
1. 對於依賴的模塊,AMD 是提前執行,CMD 是延遲執行。
2. CMD 推崇依賴就近,AMD 推崇依賴前置。
CMD 默認推薦的是
define(function(require, exports, module) { var a = require('./a') a.doSomething() // 此處略去 100 行 var b = require('./b') // 依賴可以就近書寫 b.doSomething() // ... })
AMD 默認推薦的是
define(['./a', './b'], function(a, b) { // 依賴必須一開始就寫好 a.doSomething() // 此處略去 100 行 b.doSomething() ... })
5、以下代碼會輸出什么
class Foo { constructor (name) { this.name = name } greet () { console.log('hello, this is ', this.name) } someThingAsync () { return Promise.resolve() } asyncGreet () { this.someThingAsync() .then(this.greet) } } new Foo('dog').asyncGreet()
答案:Cannot read property 'name' of undefined
解析:greet 沒有在正確的上下文中運行。,這個問題依然有很多解決方案。
asyncGreet() { this.someThingAsync() .then(this.greet.bind(this)) }
也可以在類的constructor中綁定它:
constructor(name) { this.name = name this.greet = this.greet.bind(this) }