环境搭建和简单实践
怎么es6还要环境搭建呢?我用的还是javascript吗?然而不是这么一回事。
es6在语法上有很多的变化,算是脱胎换骨了,但是因为浏览器还没有完全支持es6的新语法,所以使用es6开发,就应该先将其转化为es5,那么就需要工具来完成,
babel
Babel是一个编译器,负责将源代码转换成指定的语法的目标代码,可以使之很好的在运行环境中执行我们的代码。
安装babel的命令行工具:
//一般要先在当前项目生成一个package.json;然后将babel-cli安装在本地 ,它只是一个开发依赖。另外不同的项目依赖库的版本可能都不同,全局的babel-cli库也不能保证兼容各个项目中其他依赖库的版本。
$ npm install -D babel-cli;
安装转码规则包,Babel支持很多语法的转码,可以选择集成的。
babel-preset-env 是一个新的 preset,可以根据配置的目标运行环境(environment)自动启用需要的 babel 插件,babel-preset-env 的工作方式类似 babel-preset-latest,唯一不同的就是 babel-preset-env 会根据配置的 env 只编译那些还不支持的特性。
$ npm install -D babel-preset-env
然后编译,
//编译某个具体的js文件
$ babel index.js --out-file index-compile.js
//编译目录中所有的js文件并另存到指定目录
$ babel src --out-dir lib / $ babel src -d lib
每次都这样做,太繁琐了?试用一下这条命令。在package.json文件中的script中添加:
"build": "babel src -d lib"
它可以实现简单的编译的功能,不过这不是最好的解决方案,
因为Babel 默认只转换新的 JavaScript 句法(syntax),而不转换新的 API ,比如 Iterator、Generator、Set、Maps、Proxy、Reflect、Symbol、Promise 等全局对象,以及一些定义在全局对象上的方法(比如 Object.assign)都不会转码
为了能够完全转换es6的内容,需要安装babel-polyfill插件
1.先引入webpack,这里只是因为babel-polyfill可以在Node/Browserify/webpack中使用
//全局安装,在配置完成后,可以直接通过webpack运行,
$ npm install -g webpack
//一般会装在本地项目中,就不能直接使用webpack需要找node_module中的webpack的位置。
$ npm install -D webpack
2.安装babel-polyfill插件,babel-cli,babel-preset-env
$ npm install -save-dev babel-polyfill babel-cli babel-preset-env
3.在需要的文件中引入babel-polyfill:
import "babel-polyfill";
//node.js中引入:require('babel-polyfill');
4.配置webpack.config.js文件,将['babel-polyfill', './src/index.js'] 写到entry属性中。如下
const path = require('path');
module.exports = {
entry: ['babel-polyfill', './src/index.js'],
module: {
rules: [
{ test: /\.js$/, exclude: /node_modules/, loader: "babel-loader" }
]
},
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
}
};
5.配置.babelrc文件
{
"persets": ["env"];
}
6.启动webpack
$ webpack
promise
promise是什么?(来自sf.gg的promise百科)
Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。它由社区最早提出和实现,ES6 将其写进了语言标准,统一了用法,原生提供了 Promise 对象。
所谓 Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。Promise 提供统一的 API,各种异步操作都可以用同样的方法进行处理。
promise方法:
1.构造函数
Promise(
function(resolve, reject) {
}
);
2.实例,构造函数用于生成Promise对象
let promise = new Promise(function(resolve, reject) { });
3.基本用法
Promise链式调用的原因?
因为Promise.prototype.then方法和Promise.prototype.catch方法都返回Promise对象。所以可以链式调用
Promise对象的其他用法。
1.Promise.all()
将多个Promise实例,包装成一个新的Promise实例
let promise = Promise.all([promiseOne,promiseTwo]);
而且,只有当promiseOne 和 promiseTwo 都成功的时候,promise才会成功
2.Promise.race()
该方法同样是将多个Promise实例,包装成一个新的Promise实例。只不过在这种情况下,只要其中一个被成功调用,promise 就会被成功调用。
继续研究参考:https://segmentfault.com/a/1190000011742644
axios
基于http客户端的promise,面向浏览器和nodejs
安装:
使用 npm:
$ npm install axios
使用 bower:
$ bower install axios
引入axios.js
在bowe_components中引入axios.js
axios请求
axios.get('http://h6.duchengjiu.top/shop/api_goods.php')
.then(response => {
console.log(response.data);
});
generator & yield
1.生成器函数(Generator Function)
//声明式
function* gene() {
//...
}
//定义式
const gene = function*() {
//...
}
2.yield
yield的作用与return相似,但是yield不会退出函数体,而是切出当前函数的运行时(此处为一个类协程,Semi-coroutine),并与此同时可以讲一个值(可以是任何类型)带到主线程中。
3.使用方法:
构建生成器函数
function* genFn() {
let a = 2
yield a
while (true) {
yield a = a / (2 * a + 1)
}
}
执行generator函数
generator函数不能直接作为函数来使用,执行generator函数会返回一个生成器对象,将用于运行生成器内容和接受其中的值。
const gen = genFn()
运行生成器内容
for (const a of gen) {
if (a < 1/100) break
console.log(a)
}
迭代器
1.for-in
都知道for-in循环用来遍历对象,但是细心的你也会发现,for-in无法控制遍历的顺序,它永远都是从第一个到最后一个。
2.for-of
for-of是es6的新语法,它用来配合迭代器,迭代对象,我们可以控制迭代顺序,
3.Symbol.iterator
对象被迭代的条件是它需要有一个Symbol.iterator属性,他是一个独一无二的属性,暂不详细介绍。
4.迭代器长啥样?
iterator[Symbol.iterator] = function () {
return {
next: function () {}
}
}
//iterator[Symbol.iterator]() 它会返回一个类似于{next: function() {}}对象,原型是Array Iterator
let iterator = iterator[Symbol.iterator]();
//iterator.next(),会返回一个类似于{value: …, done: [true/false]}的对象,
iterator.next();
那么next()内部大概是这样的:
table[Symbol.iterator] = function () {
var keys = Object.keys(this).sort();
var index = 0;
return {
next: function () {
return {
value: keys[index], done: index++ >= keys.length
};
}
}
}
针对对象,自己写一个迭代器
{
let obj={
start:[1,3,2],
end:[7,9,8],
[Symbol.iterator](){
let self=this;
let index=0;
let arr=self.start.concat(self.end);
let len=arr.length;
return {
next(){
if(index<len){
return {
value:arr[index++],
done:false
}
} else {
return {
value:arr[index++],
done:true
}
}
}
}
}
// 遍历迭代器
let iterator = obj[Symbol.iterator]();
console.log(iterator);
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
}
5.惰性执行:
如果next()函数永远不被调用的话,我们就浪费了性能。所以让我们来优化它:
table[Symbol.iterator] = function () {
var _this = this;
var keys = null;
var index = 0;
return {
next: function () {
if (keys === null) {
keys = Object.keys(_this).sort();
}
return {
value: keys[index], done: index++ >= keys.length
};
}
}
}
6.内置迭代器
String,Array,TypedArray,Map和Set都是内置迭代器,因为它们的原型中都有一个Symbol.iterator方法
7.Generator函数
function* iterator(arr) {
for(let item of arr) {
yield item;
}
}
let iter = iterator([1,2,3,5,6,7]);
for(let k of iter) {
console.log(k);
}
这两种都可以用来迭代,iter是一个迭代器,像上面我们分析的那样,
它内部会返回 {next: function() { } }, for-of也是同样。
//iter.next();
//for(let k of iter) {}
8.iterables
iterable是一个概念,表示有Symbol.iterator属性的object,
这个属性指向一个generator函数,调用这个函数,会返回一个关于这个对象的iterator,
在ES6中所有的集合类对象(array, set, maps)和字符串都是iterable,并且有自己默认的iterator,
所以在使用for-of迭代的时候,每次都是利用了对象上的iterator,调用next(),
9.向迭代器中传递参数
function* createIterator() {
let first = yield 1;
let second = yield first + 2;
yield second + 3;
}
let i= createItreator()
i.next() // {value:1 done: false}
i.next(5) // {value: 7 done: false}
i.next(3) // {value: 6 done: false}e}
10.应用实例
function run(taskDef) {
let task = taskDef();
let value = task.next()
function step() {
if (!value.done) {
value = task.next(value.value)
step()
}
}
step()
}
run(function*(){
let first = yield 1;
let second = yield first + 3;
yield second + 4;
})