es6 学习笔记(一)

环境搭建和简单实践

怎么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链式调用的原因?

因为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),并与此同时可以讲一个值(可以是任何类型)带到主线程中。

继续理解:生成器(Generator) 

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;
})

11.应用实例2

 

posted @ 2017-11-14 10:37  咔嚓咔嚓卡擦  阅读(341)  评论(0编辑  收藏  举报