0、導言
ES6中新增了不少的新特性,來點測試題熱熱身。具體題目來源請看:http://perfectionkills.com/javascript-quiz-es6/。
以下將一題一題來解析what和why。
1、題目一
(function(x, f = () => x) {
var x;
var y = x;
x = 2;
return [x, y, f()];
})(1)
A、 [2, 1, 1]
B、 [2, undefined, 1]
C、 [2, 1, 2]
D、 [2, undefined, 2]
解析:本題主要考察的知識點是1、參數值與函數體內定義的重名變量的優先級;2、ES6的默認參數;3、箭頭函數。 在本題中,先執行x的定義,然后函數參數x=1,接着是y = x = 1,接着再x = 2,第三個是執行f函數,箭頭函數如果只是表達式,那么等價於return 表達式,由於箭頭函數的作用域等於定義時的作用域,那么函數定義時x=1,所以最后的return x 等價於 return 1
2、題目二
(function() {
return [
(() => this.x).bind({ x: 'inner' })(),
(() => this.x)()
]
}).call({ x: 'outer' });
A、 ['inner', 'outer']
B、 ['outer', 'outer']
C、 [undefined, undefined]
D、 Error
解析:本題主要考察的是箭頭函數的作用域問題,箭頭函數的作用域等於定義時的作用域,所以通過bind設置的this是無效的。那么結果就顯而易見了。
3、題目三
let x, { x: y = 1 } = { x }; y;
A、 undefined
B、 1
C、 { x: 1 }
D、 Error
解析:本題主要考察的是對象賦值,先定義x,然后在賦值的時候會執行一次y=1,最后返回y的值。
4、題目四
(function() {
let f = this ? class g { } : class h { };
return [
typeof f,
typeof h
];
})();
A、 ["function", "undefined"]
B、 ["function", "function"]
C、 ["undefined", "undefined"]
D、 Error
解析:本題主要考察定義函數變量時,命名函數的名稱作用域問題。在定義函數變量時,函數名稱只能在函數體中生效。
5、題目五
(typeof (new (class { class () {} })))
A、 "function"
B、 "object"
C、 "undefined"
D、 Error
解析:本題主要考察對象的類型,和原型方法。該提可以分解如下:
// 定義包含class原型方法的類。
var Test = class{
class(){}
};
var test = new Test(); //定義類的實例
typeof test; //出結果
6、題目六
typeof (new (class F extends (String, Array) { })).substring
A、 "function"
B、 "object"
C、 "undefined"
D、 Error
解析:本題主要考察ES6中class的繼承,以及表達式的返回值和undefined的類型。題目其實可以按照如下方式分解:
//由於JS的class沒有多繼承的概念,所以括號被當做表達式來看
(String, Array) //Array,返回最后一個值
(class F extends Array); //class F繼承成Array
(new (class F extends Array)); //創建一個F的實例
(new (class F extends (String, Array) { })).substring; //取實例的substring方法,由於沒有繼承String,Array沒有substring方法,那么返回值為undefined
typeof (new (class F extends (String, Array) { })).substring; //對undefined取typeof
7、題目七
[...[...'...']].length
A、 1
B、 3
C、 6
D、 Error
解析:本題主要考察的是擴展運算符...的作用。擴展運算符是將后面的對象轉換為數組,具體用法是:
[...<數據>] 比如 [...'abc']等價於["a", "b", "c"]
8、題目八
typeof (function* f() { yield f })().next().next()
A、 "function"
B、 "generator"
C、 "object"
D、 Error
解析:本題主要考察ES6的生成器。題目可以如下分解:
function* f() { yield f }; //定義一個生成器
var g = f(); //執行生成器
var temp = g.next(); //返回第一次yield的值
console.log(temp); //測試,查看temp,其實是一個object
temp.next();//對對象調用next方法,無效
9、題目九
typeof (new class f() { [f]() { }, f: { } })[`${f}`]
A、 "function"
B、 "undefined"
C、 "object"
D、 Error
解析:本題主要考察ES6的class,以及動態屬性和模板字符串等。 實際上這個題動態屬性和模板字符串都是煙霧彈,在執行new class f()的時候,就已經有語法錯誤了。
10、題目十
typeof `${{Object}}`.prototype
A、 "function"
B、 "undefined"
C、 "object"
D、 Error
解析:本題考察的知識點相對單一,就是模板字符串。分解如下:
var o = {Object},
str = `${o}`;
typeof str.prototype;
11、題目十一
((...x, xs)=>x)(1,2,3)
A、 1
B、 3
C、 [1,2,3]
D、 Error
解析:本題主要考察的是Rest參數的用法,在ES6中,Rest參數只能放在末尾,所以該用法的錯誤的。
12、題目十二
let arr = [ ];
for (let { x = 2, y } of [{ x: 1 }, 2, { y }]) {
arr.push(x, y);
}
arr;
A、 [2, { x: 1 }, 2, 2, 2, { y }]
B、 [{ x: 1 }, 2, { y }]
C、 [1, undefined, 2, undefined, 2, undefined]
D、 Error
解析:本題看起來是考察let的作用域和of迭代的用法。實則是考察let的語法,let之后是一個參數名稱。所以,語法錯誤
13、題目十三
(function() {
if (false) {
let f = { g() => 1 };
}
return typeof f;
})()
A、 "function"
B、 "undefined"
C、 "object"
D、 Error
解析:本題非常有迷惑性,看似考察的let的作用域問題,實則考察了箭頭函數的語法問題。
14、題目答案
相信大家看過題目的解析,對題目答案已經了然。為了完善本文,還是在最后貼出所有題目的答案:
ABBAB CBDDB DDD