ES6笔记(完整版1)

186 阅读14分钟

一、环境搭建 

(一)Node介绍

  • Node也叫Node.js,由Ryan-Dahl于2009年5月在GitHub发布了第一版
  • Node是一个javascript运行环境(runtime)。实际上他是对Google V8引擎进行了封装
  • 官网介绍:一个搭建在ChromeJavaScript运行时上的平台,用于构建高速、可伸缩的网络程序
  • Node采用的时间驱动、非阻塞I/O模型,使它既轻量又高效,并成为构建运行在分布式设备上的数据密集型实时程序的完美选择
  • 目前Node在实际开发中主要作为开发基础环境存在,用于进行模块管理,编译es6代码,运行各种js脚本

(二)Ndode安装

1、下载

进入官网nodejs.org/en/,选取合适的版本…

2、安装

Linux:先将安装包解压,然后进行环境变量的配置
windows:直接点击安装即可

(三)Node使用

1、基本使用

1)执行js脚本
$ node demo.js
2)REPL环境
在命令键入node命令,后面没有文件名,就进入一个Node.js的REPL环境(Read-eval-print-loop,"读取-求值-输出循环"),可以直接运行各种JavaScript命令
$ node
> 1+1
2
>

(四)模块化结构

1、模块化

  • Node.js采用模块化结构,按照commonJS规范定义和使用模块

  • 在Node中,以模块为单位划分所有功能,并且提供一个完整的模块加载机制,使得我们可以将应用程序划分为各个不同的部分,并且对这些部分很好的协同管理

  • 通过将各种可重用的代码编写在各种模块中的方法,我们可以大大的减少应用程序的代码量,提高应用程序开发效率以及应用程序的可读性

  • 通过模块加载机制,我们也可以将各种第三方模块引入到我们的应用程序中

1)commonJS

  • JavaScript是一种功能强大的面向对象语言,具有一些最快速的动态语言解释器

  • 官方JavaScript规范定义了一些用于构建基于浏览器应用程序的对象的API。但是,规范并没有定义一个用于构建更广泛的程序的标准库

  • commonJS API将通过定义处理许多常见应用程序需求的API来填补这一空白,最终提供与Python、Ruby和Java一样丰富的标准库。其意图是应用程序开发人员能够使用commonJS API编写应用程序,然后在不同的JavaScript解释器和主机环境中运行该程序

  • 在兼容commonJS的系统中,可以使用JavaScript程序开发

    服务器端JavaScript应用程序 命令行工具 图形界面应用程序 混合应用程序(如Titanium或Adobe AIR)

Node应用由模块组成,采用commonJS模块规范

2)模块作用域

每一个文件都是一个模块,有自己的作用域

在一个文件里面定义的变量,函数,类,都是私有的,对其他文件不可见

私有属性:
    //example.js
    var x = 5;
    var addx = function(value){
        return value+x
    }
上面代码中,变量x和函数addx,是当前文件example.js私有的,其他文件不可见

全局属性:
    如果想在多个文件分享变量,必须定义为global对象的属性、
    global.warning = true

3)模块交互

commonJS规范规定,每个模块内部,module变量代表当前模块。这个变量是一个对象,它的export属性(即 module.exports)是对外的接口。

加载摸个模块,其实是加载该模块的module.exports属性

定义模块:
    var x = 5;
    var addX = function(value){
        return value+x;
    };
    module.export.x = x;
    module.export.addX = addX;

模块加载:
    require方法用于加载模块
    var example = require('./example.js')
    console.log(example.x);//5
    console.log(example.addX(1));//

4)模块对象

Node内部提供一个module构建函数

所有模块都是module的实例,每个模块内部都有一个module对象,代表当前模块

它有以下属性:

module.id 模块的识别符,通常是带有对对路径的模块文件名
module.filename 模块的文件名,带有绝对路径
module.loaded 返回一个布尔值,表示模块是否已经加载完成
module.parent 返回一个对象,表示调用该模块的模块
module.children 返回一个数组,表示该模块要用到的其他模块
module.exports 表示模块对外输出的值

5)exports变量

为了方便,Node为每个模块提供一个export变量,指向module.exports
这等同于在每个模块头部,有这样一行命令:
var export = module.exports

(五)核心模块

1)path模块:

path模块提供看一些工具函数,用于处理文件与目录的路径,使用方法如下:

var path = require('path');
path.basename() 该方法返回参数路径的最后一个部分
path.dirname() 该方法返回一个path的目录名
path.extname() 该方法返回path的扩展名,即从path的最后一部分中的最后一个。(句号)字符到字符串结束
path.isAbsolute() 该方法判定path是否为一个绝对路径
path.join() 该方法使用平台特定的分隔符把全部给定的path片段连接到一起,并规范生成的路径
path.nomalize() 该方法会规范化给定的path,并解析'..''.'片段
path.delimiter 该属性提供平台特定的路径分隔符

2)querystring模块:

querystring模块提供了一些使用函数,用于解析与格式化URL查询字符串。使用如下方法引用:
var querystring = require('querystring')
querystring.stringify(obj[,sep[,eq]]) 将对象转换为查询字符串
    obj 要序列化成URL查询字符串的对象
    sep 用于界定查询字符串中的键值对的子字符串。默认为'&'
    eq 用于界定查询字符串中的键与值的子字符串。默认为'='
querystring.parse(str[,sep[,eq]])  将查询字符串转为对象

3)url模块:

提供了一些实用函数,用于URL处理与解析。可以通过以下方式使用:
var url = require('url')
url.parse() 将一个url地址转换为一个对象
url.resolve() 该方法会以一种web浏览器解释超链接的方式吧一个目标URL解析成相对于一个基础url
    url.resolve('/one/two/three/','four');//'/one/two/four'
    url.reolve('http://example.com/','one'); //'http://example.com/one'
    url.resolve('http://example.com/one','/two'); //'http://example.com/two' (替换最后一个)

(六)npm

1)简介:

  • npm是js开发者能够更方便的分享和复用以及更新代码,被复用的代码成为包或者模块,一个模块中包含了一个或多个js文件。
  • 在模块中一般还会包含一个package.json文件,该文件中包含了该模块的配置信息。一个完整的项目需要依赖多个模块
  • 一个完整的npm包含三个部分
  1. npm网站 --- 用于预览npm管理的包
  2. 注册机制 --- 用于上传包,使用数据库来维护包与上传者的信息
  3. 客户端 --- 用于安装包

2)创建一个模块:

Node.js的模块是一种能够被发布到npm上的包
创建模块从创建package.json文件开始,package.json是模块的配置文件
可以使用npm.init命令来初始化package.json文件
    $npm init 
        name:模块名称
        version:模块版本
        description:描述信息
        main:指定模块入口文件
        Dependencies:依赖关系 
        devDependencies:环境依赖或测试依赖
        engines:指定node版本
        optionalDependencies:可选择依赖
        script:定义当前模块脚本,使用npm run 来运行所定义的脚本
使用-y参数创建默认package.json文件
    $ npm init -y

3)安装npm:

npm 会随着Node一起被安装到本地,可以使用以下命令来更新npm:
$ npm install npm@latest -g
安装淘宝镜像:
    由于默认的npm仓库在国外,下载起来很慢,可以使用淘宝镜像来加快下载速度
    $ npm install -g cnpm --register=https://register.npm.taobao.org
    Registry注册中心:
        官方:https://registry.npmjs.org
        淘宝:https://registry.npm.taobao.org
        私有:http://localIP:port
修改npm权限:
    执行npm的时候有时候会遇到权限不足的情况,可以通过以下方式进行修正:
    $ npm config get prefix
    $ sudo chown -R $(whoami) $(npm config get prefix)/{lib/node_modules,bin,share}

4)模块安装:

如果想要仅在当前模块中使用某个第三方模块,就可以使用npm install的默认安装,默认安装即是本地安装;
如果想在命令行中使用模块,就需要进行全局安装。
安装时,如果当前目录中没有node_modules目录,npm就会创建一个该目录
$ npm install <package_name>
    $ npm install
        安装所有项目依赖的模块,依赖的模块定义在package.json中
    $ npm install
        安装模块时,默认会将所安装的模块写入到package.json中的dependencies属性,通过添加一些参数改变这个特性
        -S, --save
        -D, --save-dev:Package will appear in your devDependencies
        -O, --save-optional:Package will appear in your optionalDependencies
        --no--save:Prevents saving to dependencies
        -E, --Save-exact:saved dependencies will be configured with an exact version rather than using npm's default semver range operator

5)模块更新:

全局更新依赖的模块
$ npm update <modules_name>

6)模块删除:

从node_modules删除不需要的模块
$ npm uninstall -g <package_name>
不仅删除node_modules中的依赖,还需要删除package.json中的信息,可以使用--save参数
$ npm uninstall --save -g <package_name>

(七)Babel

1、命令行转码babel-cli

全局环境下进行babel转码。这意味着,如果项目要运行,全局环境必须有babel,也就是说项目产生了对环境的依赖
1)安装
    $ npm install --globel babel-cli
2)安装预设并且添加配置文件配置.babelrc
    在当前项目的根目录下创建该文件
    $ npm install --save-dev babel-preset-es2015
    {"presets":["es2015"]}
2)使用
    转码结果输出到标准输出
    $ babel example.js
    转码结果写入一个文件,--out-file或-o参数指定输出文件
    $ babel example.js --out-file compiled.js
    整个目录转码--out-dir或-d参数指定输出目录
    $ babel src --out-dir lib

2、配置文件

babel的配置文件是.babelrc,存放在项目的根目录下
使用babel的第一步,就是配置这个文件。该文件用来设置转码规则和插件,基本格式如下:
{"presets":[],"plugins":[]}
1)preset字段设定转码规则,官方提供一下的规则集,你可以根据需要安装
    ES2015转码规则
    $ npm install --save-dev babel-preset-es2015 =>es2015
    最新转码规则
    $ npm install --save-dev babel-preset-latest =>latest
    不会过时的转码规则
    $ npm install --save-dev babel-preset-nev =>env
2)然后,将这些规则加入.babelrc
     {"presets":["es2015"],"plugins":[],"ignore":[]}

3、将babel-cli安装到项目中

1)安装babel-cli及预设
$ npm install --save-dev babel-cli
$ npm install --save-dev babel-preset-env
2)配置文件.babelrc
    $ vim.babelrc
        {"preset":["env"]}
3)在package.json中添加脚本
    {
      //...
      "script":{"build":"babel src -d lib"}
    }   
4)运行脚本,执行转码操作
    $ npm run build

(八)babel-polyfill

babel默认只转换新的JavaScript语法(syntax),而不转换新的API
比如Iterator,GeneratorSetMapsProxyReflectSymbolPromise等全局对象
以及一些定义在全局对象上的方法(Object.assign)都不会转码
举例来说:
ES6Array对象上新增了Array.from方法,babel就不会转码这个方法
如果想让这个方法运行,必须使用babel-polyfill,为当前环境提供一个垫片

1、安装

$ npm install -save babel-polyfill

2、在js文件中引用并且使用

import "babel-polyfill";//或者require("babel-polufill")

第二章 基础知识

一、let命令

1、基本用法

ES6新增了let命令,用来声明变量。用法类似于var,但是也存在新特性:
1let所声明的变量,只在let命令所在的代码块有效。适用于for循环
    {let a = 10;var b = 1;}
       //a  a is not defined
       //b  1
2)不存在变量提升
    console.log{bar}
    let bar = 2;
    //报错RederenceRrror:bar is not defined
3)暂时性死区
    在代码块内,使用let命令变量之前,该变量都是不可用的
    var tmp = 123;
    if(true){
        tmp = 'abc'; //ReferenceError
        let tmp;
    }
4)不允许重复声明
    function(){let a = 10; let a = 1;} //报错

2、块级作用域

let实际上位JavaScript新增的块级作用域。
外层作用域无法读取内层作用域的变量,内层作用域可以定义外层作用域的同名变量
let foo = 1;
{
    let foo = 2;//定义同名变量
    let bar = "one";
}
console.log{foo};//1
console.log(bar);//报错
块级作用域的出现,实际上使得广泛应用的立即执行函数表达式(IIFE)不再必要了

二、const命令

1、基本用法

const声明一个只读的变量。一旦声明,常量的值就不能改变
const PI = 3.1415;
PI = 3;//TypeRrror:Assignment to constant variable

1)const声明的变量不得改变值,这意味着,const一旦声明,就必须立即初始化,不能留到以后赋值

const foo; //SyntaxErroe:Missing initializer in const declaration

2)块级作用域

只在声明所在的块级作用域内有效

3)暂时性死区

在代码块内,使用let命令声明变量之前,该变量是不可用
if(true){
    console.log(MAX);//ReferenceError const MAX = 5;
}

4)不允许重复声明

var message = 'hello'
let age = 25;
//以下两行都会报错
const message = 'goodbye'
const age = 30

三、解构赋值

1、解构

ES6允许按照一定模式,从数组和对象中取值,对变量进行赋值,这被称为解构(Destructing)
例如:let [a,b,c] = [1,2,3]
本质上,这种写法属于“模式匹配”,只要等号两边的模式相同,左边的变量就会被赋予对应的值
如果解构不成功,变量的值就等于undefined。另一种情况是不完全解构,即等号左边的模式只匹配一部分等号右边的数组。
这种情况下,解构依然成功

2、数组的解构赋值

let [a,b,c] = [1,2,3]
1)不完全解构:
    let [a,[b],d] = [1,[2,3],4]; //a=1;b=2;d=4
2)集合解构:
    let[head,...tail] = [1,2,3,4]; //head=1;tail=[2,3,4]
3)默认值(当匹配值严格等于undefined时,默认值生效)
    let [x,y='b'] = ['a']; //x = 'a' ,y = 'b'
4)默认值也可以为函数
    function f(){console.log('aaa');}
    let [x=f()] =[1]

3、对象的解构赋值

1)对象的属性没有次序,变量必须与属性同名,才能取到正确的值
    let {foo,bar} = {foo:'aaa',bar:'bbb'}; //foo='aaa';bar='bbb'
2)如果变量名与属性名不一致,必须写成下面这样
    var {foo:baz} = {foo:'aaa',bar:'bbb'}; //baz='aaa'
3)这实际上说明,对象的解构赋值是下面形式的简写
    let {foo:foo,bar:bar} = {foo:'aaa',bar:'bbb'}
4)嵌套解构:
    let obj = {p:['Hello',{y:'World'}]}
    let {p:[x,{y}]} = obj; //x='Hello'; y='World'
5)默认值(默认值生效的条件是:对象的属性值严格等于undefined)
    var {x:y=3} = {}; //y=3

4、字符串的解构赋值

1)解构时,字符串被转换成了一个类似数组的对象
    const [a,b,c,d,e] = 'hello'; //a=h;b=e;c=l;d=l;e=o
2)也可以对数组的属性解构
    let {length:len} = 'hello'; //len =5

5、数值和布尔值的解构赋值

解构时,如果等号右边是数值和布尔值,则会先转为对象
let {toString:s} = 123; //s === Number.prototype.toString true
let {toString:s} = true; //s === Boolean.prototype.toString true

6、函数参数的解构赋值

1)基本语法
    function add([x,y]){return x+y;}
    add([1,2])
2)默认值
    function move({x=0,y=0}){
        return [x,y]
    }
    move({x:3,y:8});//[3,8]
    move({x:3}); //[3,0]
    move({}); //[0,0]
    move(); //[0,0]

7、常见用途

1)交换变量的值
    let x = 1;
    let y = 2;
    [x,y] = [y,x]

2)从函数返回多个值
    function example(){
        return [1,2,3]
    }
    let [a,b,c] = example();

3)函数参数的定义
    function f([x,y,z]){...}
    f([1,2,3])
    
4)提取json数据
    let jsonData = {id:42,status:'OK',data:[867,5309]};
    let {id,status,data:number} = jsonData;

5)输入模块的指定方法
    const {SourceMapConsumer,SourceNode} = require("source-map")

6)函数参数的默认值
    jQuery.ajax = function(url,{
        async = true,
        cache = true,
        global = true,
        beforeSend = function(){},
        complete = function(){},
        // ...more config
    }){// ...do stuff}
    指定参数的默认值,就避免了在函数体内部在写var foo = config.foo||'default foo';
    这样的语句

7)遍历map结构
    var map = new Map();
    map.set('first','hello');
    map.set('second','world')l
    for(let[key,value] of map){
        console.log(key + "is" +value)
    }

第三章 对象、函数、数组的扩展

学习目标:

  1. 属性简写方式
  2. 方法简写方式
  3. object方法的扩展
  4. 函数默认值
  5. 箭头函数
  6. 扩展运算符
  7. Array.from()
  8. Array.of()
  9. 数组实例的find(),findIndex()
  10. 数组的实例fill()
  11. 数组实例的entries(),keys(),values()
  12. 数组实例的includes()

一、对象扩展

1、属性简写

ES6允许直接写入变量和函数,作为对象的属性和方法。这时,属性名为变量名,数值型为变量值
    var foo = 'bar';
    var baz = {foo}
    =>
    var baz = {foo:foo}

2、方法简写

var o  = {method(){return "hello!";}};
=>
var o  = {method:function(){return "hello"}}

3、属性名表达式

ES6允许字面量定义对象时,可以把表达式放在方括号内
    let propKey = 'foo';
    let obj = {[propKey]:true,['a'+'bc']:123}

4、方法的的name属性

函数的name属性,返回函数名
    const person = {sayName(){console.log('hello!');}};
    person.sayName.name; //"sayName"

5、Object(value1,value2)

同值相等,与===类似,不同之处在于:+0不等于-0NAN等于自身
    Object.is('foo','foo');//true
    Object.is({},{}); //false

二、函数的扩展

1、函数参数的默认值

ES6允许为函数的参数设置默认值,即直接写在参数定义的后面
    function log(x,y='World'){
        console.log(x,y)
    }
通常情况下,定义了默认值的参数,应该是函数的尾参数
函数的length属性,将返回没有指定默认值的参数个数

2、与解构赋值默认值结合使用

参数默认值可以与解构赋值的默认值结合起来使用
function foo({x,y=5}){
    console.log(x,y)
}
foo({});//undefined 5
foo({x:1}); //1 5
foo({x:1,y:2}); //1 2

3、rest参数

ES6引入rest参数(形式为“...变量名”),用于获取函数的多余参数,这样就不需要使用arguments对象了
rest参数搭配的变量是一个数组,改变量将多余的参数放入数组中
function add(...values){
    let sum = 0;
    for(var val of values){
        sum += val
    }
    return sum
}
add(2,3,5); //10

4、箭头函数

ES6允许使用“箭头”(=>)定义函数
1)基本用法:
var f = v => v;
等价于
var f = function(v){
    return v;
}
如果箭头函数不需要参数或需要多个参数,就使用一个圆括号代表参数部分
如果箭头函数的代码块部分多于一条语句,就要使用大括号将他们括起来,并且使用return语句返回

2this
箭头函数里面没有自己的this,而是引用外层的this
//ES6
function foo(){
    setTimeout(()=>{
        console.log('id:',this.id)
    },1000)
}

//ES5
function foo(){
    var _this = this;
    setTimeout(function(){
        console.log('id:',_this.id);
    },1000)
}

不能作为构造函数,没有内部属性arguments

5、扩展运算符

扩展运算符(spread)是三个点(...)。它好比rest参数的逆运算,讲一个数组转为用逗号分隔的参数序列
console.log(...[1,2,3]); //1,2,3

1)函数的调用
function add(x,y){
    return x+y
}
add(...[1,3]);
Math.max(...[14,3,77]);

2)将字符串转为数组
[...'hello'] //['h','e','l','l','o']