JS部分
HTML + CSS
React
Vue
ES6
webpack,node.js,Git等
ES6 阮一峰ES6入门教程
1.使用箭头函数应注意什么?
(1)函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象
(2)不能够使用arguments对象
(3)不能用作构造函数,所以不能使用new命令,否则会报错
(4)不可以使用yield命令,因此箭头函数不能用作 Generator 函数
(5)没有原型和super
(6)call/apply/bind方法无法改变箭头函数中this的指向
2.简述es6的新特性
- 增加块作用域
- 增加let const
- 解构赋值
- 函数参数扩展 (函数参数可以使用默认值、不定参数以及拓展参数)
- 增加class类的支持
- 增加箭头函数
- 增加模块和模块加载
- 增加新的API math, number, string, array, object
3.ES6 module和commonjs的区别
JavaScript 一直没有模块(module)体系,无法将一个大程序拆分成互相依赖的小文件,在 ES6 之前,社区制定了一些模块加载方案,最主要的有 CommonJS 和 AMD 两种。前者用于服务器,后者用于浏览器。ES6 在语言标准的层面上,实现了模块功能,而且实现得相当简单,完全可以取代 CommonJS 和 AMD 规范,成为浏览器和服务器通用的模块解决方案。ES6 可以在编译时就完成模块加载,效率要比 CommonJS 模块的加载方式高
ES6module的语法
4.ES6中的Generator
Generator函数是ES6提供的一种异步编程解决方案。语法上,Generator可以理解为是一个状态机,封装了多个内部状态。执行 Generator 函数会返回一个遍历器对象,也就是说,Generator 函数除了状态机,还是一个遍历器对象生成函数。返回的遍历器对象,可以依次遍历 Generator 函数内部的每一个状态。
- Generator写法
下面四种写法均可
function * foo(x, y) { ··· }
function *foo(x, y) { ··· }
function* foo(x, y) { ··· } // 推荐写法
function*foo(x, y) { ··· }
- 执行机制
每次调用next方法,内部指针就从函数头部或上一次停下来的地方开始执行,直到遇到下一个yield表达式(或return语句)为止。换言之,Generator 函数是分段执行的,yield表达式是暂停执行的标记,而next方法可以恢复执行。
function* helloWorldGenerator() {
yield 'hello';
yield 'world';
return 'ending';
}
var hw = helloWorldGenerator();
hw.next() // { value: 'hello', done: false }
hw.next() // { value: 'world', done: false }
hw.next() // { value: 'ending', done: true }
hw.next() // { value: undefined, done: true }
调用 Generator 函数,返回一个遍历器对象,代表 Generator 函数的内部指针。以后,每次调用遍历器对象的next方法,就会返回一个有着value和done两个属性的对象。value属性表示当前的内部状态的值,是yield表达式后面那个表达式的值;done属性是一个布尔值,表示是否遍历结束。
- 与 Iterator 接口的关系
由于 Generator 函数就是遍历器生成函数,因此可以把 Generator 赋值给对象的Symbol.iterator属性,从而使得该对象具有 Iterator 接口。
var myIterable = {};
myIterable[Symbol.iterator] = function* () {
yield 1;
yield 2;
yield 3;
};
[...myIterable] // [1, 2, 3]
- next()的参数
yield表达式本身没有返回值,或者说总是返回undefined。next方法可以带一个参数,该参数就会被当作上一个yield表达式的返回值。
function* foo(x) {
var y = 2 * (yield (x + 1));
var z = yield (y / 3);
return (x + y + z);
}
var a = foo(5);
a.next() // Object{value:6, done:false}
a.next() // Object{value:NaN, done:false}
a.next() // Object{value:NaN, done:true}
var b = foo(5);
b.next() // { value:6, done:false }
b.next(12) // { value:8, done:false }
b.next(13) // { value:42, done:true }
上面代码中,第二次运行next方法的时候不带参数,导致 y 的值等于2 * undefined(即NaN),除以 3 以后还是NaN,因此返回对象的value属性也等于NaN。第三次运行Next方法的时候不带参数,所以z等于undefined,返回对象的value属性等于5 + NaN + undefined,即NaN。
如果向next方法提供参数,返回结果就完全不一样了。上面代码第一次调用b的next方法时,返回x+1的值6;第二次调用next方法,将上一次yield表达式的值设为12,因此y等于24,返回y / 3的值8;第三次调用next方法,将上一次yield表达式的值设为13,因此z等于13,这时x等于5,y等于24,所以return语句的值等于42。
注意,由于next方法的参数表示上一个yield表达式的返回值,所以在第一次使用next方法时,传递参数是无效的。V8 引擎直接忽略第一次使用next方法时的参数,只有从第二次使用next方法开始,参数才是有效的。从语义上讲,第一个next方法用来启动遍历器对象,所以不用带有参数。
Genterator应用
- 异步操作的同步化表达
Generator 函数的暂停执行的效果,意味着可以把异步操作写在yield表达式里面,等到调用next方法时再往后执行
//Genterator实现异步请求数据
function* main() {
var result = yield request("http://some.url");
var resp = JSON.parse(result);
console.log(resp.value);
}
function request(url) {
makeAjaxCall(url, function(response){
it.next(response);
});
}
var it = main();
it.next();
- 控制流管理
如果有一个多步操作非常耗时,采用回调函数,可能会写成下面这样。
Promise.resolve(step1)
.then(step2)
.then(step3)
.then(step4)
.then(function (value4) {
// Do something with value4
}, function (error) {
// Handle any error from step1 through step4
})
.done();
//Generator改造后
function* longRunningTask(value1) {
try {
var value2 = yield step1(value1);
var value3 = yield step2(value2);
var value4 = yield step3(value3);
var value5 = yield step4(value4);
// Do something with value4
} catch (e) {
// Handle any error from step1 through step4
}
}