@dudusky
2017-05-06T01:47:15.000000Z
字数 11404
阅读 2351

// 课堂笔记https://www.zybuluo.com/dudusky/note/708025// 课程资料git clone https://github.com/dudusky/ES6_tutorial_demo.gitgit clone https://github.com/dudusky/es6-tutorial.git
ES6的背景和概念 , 以及亮点.
解决了哪些ES5没有解决的问题(面试问题)?
检查当前Node环境对ES6的支持情况
$ npm install -g es-checker$ es-checker

Babel是一个ES6转码器, 可以将ES6代码转换为ES5代码.
好处是可以使用ES6的语法, 而不用担心当前的环境是否完全支持ES6.
例如使用箭头函数, Babel可以将其转换为普通函数, 就能在不支持ES6的环境中执行了.
Babel在线转换http://babeljs.cn/repl/
In
//ES6 arrow function[1, 2, 3].map((n) => n + 1);
Out
[1, 2, 3].map(function(n) {return n + 1;});
babel_test的文件夹.[1, 2, 3].map((n) => n + 1);, 保存为es6.js.src和lib.package.json文件和.babelrc文件(参见第三点).在node官网安装node.js, 然后就可以使用npm包管理工具来安装babel-cli命令行工具
# 在项目目录如d:\babel_test\下安装babel-cli$ npm install --save-dev babel-cli# 安装最新的转码规则$ npm install --save-dev babel-preset-latest
.babelrc文件和package.json文件(可选)注意, 所有 Babel工具和模块的使用,都必须先写好
.babelrc.
pakage.json配置内如下:
{"devDependencies": {"babel-cli": "^6.0.0"},"scripts": {"build": "babel src -d lib"},}
.babelrc配置内容如下:
{"presets": ["latest"],"plugins": []}
# es6.js为ES6代码 使用bable命令编译要转换的ES6代码$ babel es6.js# 使用-o指令 将转码结果写入到一个文件$ babel es6.js -o es5.js# 使用-d 将ES代码所在目录转码到另外一个目录$ babel src -d lib# 如果配置好package.json文件 可以使用以下快捷方式 等同于src -d lib$ npm run build
babel-plyfull可以转换babel不能转换的语法.
babel默认只转换JavaScript的语法, 而不转换新的 API, 比如Iterator,Set,Maps,Promise等全局对象.
安装如下
$ npm install --save babel-polyfill
使用方式
import 'babel-polyfill';//或者require('babel-polyfill');

Webpack 是一个模块打包器。它将根据模块的依赖关系进行静态分析,然后将这些模块按照指定的规则生成对应的静态资源。
优势:
通过 npm 在全局环境下安装 webpack:
全局安装
$ npm install webpack -g
建议在项目下安装一份局域的 webpack:
$ npm install webpack --save-dev
// 创建一个 package.json文件,用于保存项目版本、依赖关系等$ npm init -y
$ npm install webpack --save-dev
这时项目下有两个内容:
package.json 文件
node_modules 文件夹
创建一个index.html文件
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>webpack 教程</title></head><body><script src="./bundle.js"></script> <!-- 在 index.html 文件中添加这一行代码 --></body></html>
module.exports = {entry: './main.js',output: {path: __dirname, // 输出文件的保存路径filename: 'bundle.js' // 输出文件的名称}}
main.js 或它所引用的模块的变化通知webpack,重新生成 bundle.js
// 实时监控你的js代码$ webpack --watch
在全局环境中安装 webpack-dev-server
// 安装服务器, 实时更新你的js代码$ npm install webpack-dev-server -g
在项目根目录下执行命令:
$ webpack-dev-server
在http://localhost:8080/webpack-dev-server/index.html 网址上打开index.html
$ npm install jquery --save// 更多
import $ from 'jQuery'
// 使用babel 将ES6转成ES5
* 安装 babel-loader
$ npm install babel-loader babel-core babel-preset-es2015 --save-dev
在 module.exports 值中添加 module:
module.exports = {entry: {app: ['./main.js']},output: {filename: 'bundle.js'},module: {loaders: [{test: /\.js$/,loaders: ['babel?presets[]=es2015'],exclude: /node_modules/}]}}
项目结束后,代码要压缩、混淆、合并等,只需要在命令行执行
* 安装 css-loader 和 style-loader
合并css文件
// 安装在本地, 不要使用全局安装$ npm install css-loader style-loader
// style.cssbody {background: yellow;}
// entry.jsdocument.write("改变我的颜色看看!");
// index.html<html><head><meta charset="utf-8"></head><body><script type="text/javascript" src="bundle.js" charset="utf-8"></script></body></html>
$ Webpack ./entry.js bundle.js
// contentmodule.exports = "现在试试是我在工作吗?";
$ Webpack ./entry.js bundle.js
// entry.jsrequire("./style.css");document.write(require("./content.js"));
$ webpack ./entry.js bundle.js --module-bind 'css=style!css'
ES6开发中最常用语法介绍和案例.
let和const暂时性死区(TDZ)
基本用法和常见错误
let pet = "dog";if(ture) {let a = 10;var b = 20;}a//b////TDZfunction fun() {console.log(name);let name = "Tidy";}
作用域
var myVar = "golobal var"function fun() {console.log(`函数体顶部未声明前的var: myVar: ${myVar} `)var myVar = "function var"if(true) {var myVar = "block var"console.log(`if语句里的var:myVar: ${myVar}`)}console.log(`函数体底部声明后的var: myVar: ${myVar}`)}console.log(`全局作用域下的var: myVar: ${myVar} `)fun()
暂时性死区(TDZ)
基本用法和常见错误
const PI = Math.PIPI = 23 // TypeError: Assignment to constant variable / "PI" is read-only 不能重新赋值const MY_COLOR // SyntaxError: Missing initializer in const declaration 初始化需赋值//TDZif (true) {console.log(MAX); // ReferenceErrorconst MAX = 5; //必须先声明后使用}
代码演示: 由let, const, var声明的变量在不同情况下Global, function, Block的作用域
问题: let, var, const的区别有哪些? 它们有什么特定的使用场景?
变量的结构赋值
let singer = { first: "Bob", last: "Dylan" };let { first: f, last: l } = singer; // 相当于 f = "Bob", l = "Dylan"let [x, y] = [1, 2, 3]; // x = 1, y = 2
函数参数的结构赋值
function add([x, y]) {return x + y;}console.log(add([2, 4])); //6
为函数参数设置初始值
//ES6参数赋值function f(x, y = 10, z = 20) {return x + y + z;}f(2) //32//ES5函数中的参数不能赋值function f (x, y, z) {if (y === undefined)y = 7;if (z === undefined)z = 42;return x + y + z;};f(1) //50
设置更多的参数作为一个数组(与类数组argument不同), 好处是可以使用数组方法.
function f (x ,y, ...restAr) {var a = restArconsole.log(a) //arrayconsole.log(a.length) //4return console.log(((x + y) * a.length)) //12}f(1, 2, "hi", 9, 20, 55)
数组参数
连接数组
//使用ES6var params = [ "hello", true, 7 ]var other = [ 1, 2, ...params ] // [ 1, 2, "hello", true, 7 ]//ES5写法var params = [ "hello", true, 7 ];var other = [ 1, 2 ].concat(params); // [ 1, 2, "hello", true, 7 ]
将字符串字符分割转换为数组
//使用ES6var str = "foo"var chars = [ ...str ] // [ "f", "o", "o" ]//使用ES5var str = "foo"var chars = str.split(""); // [ "f", "o", "o" ]
模板字符串(template string)
用反引号标识(Esc键下方). 它可以当作普通字符串使用, 也可以用来定义多行字符串, 或者在字符串中嵌入变量.
// 普通字符串`In JavaScript '\n' is a line-feed.`// 多行字符串`In JavaScript this isnot legal.`console.log(`string text line 1 string text line 2`);// 字符串中嵌入变量var name = "Bob", time = "today";`Hello ${name}, how are you ${time}?`//在模板字符串中使用反引号, 需要使用反斜杠转义var greeting = `\`Yo\` World!`;
案例
// 使用模板字符串拼接字符串var customer = {name: "Ros"};var friut = {amount: 10,tag: "apple",price: 5};var message = `你好! ${customer.name},你要买${friut.amount}个${friut.tag}对吗?一共是${friut.amount * friut.price}元`
repeat(number)
返回一个新字符串, 表示将原字符串重复 n 次.
"abc".repeat(2) //"abcabc"
用于将可遍历的对象转为真正的数组
基本用法
// 将一个类数组对象转换为数组(function () {var args = Array.from(arguments);return args;})(1, 2, 3); // [1, 2, 3]// ES5的写法var arr1 = [].slice.call(arrayLike); // ['a', 'b', 'c']// ES6的写法let arr2 = Array.from(arrayLike); // ['a', 'b', 'c']// 将类数组对象(arguments)转换成数组(function () {var args = Array.from(arguments);return args;})(1, 2, 3); // [1, 2, 3]
将一个数组的所有元素从开始索引填充到结束索引
//语法 value表示填充的值 start(可选)开始索引//end(可选)结束索引arr.fill(value, start, end)
基本案例
[1, 2, 3].fill(4) // [4, 4, 4][1, 2, 3].fill(4, 1) // [1, 4, 4][1, 2, 3].fill(4, 1, 2) // [1, 4, 3][1, 2, 3].fill(4, 1, 1) // [1, 2, 3][1, 2, 3].fill(4, -3, -2) // [4, 2, 3][1, 2, 3].fill(4, NaN, NaN) // [1, 2, 3]Array(3).fill(4); // [4, 4, 4]
- map() 方法创建一个新数组.
- map() 方法会给原数组中的每个元素都按顺序调用一次 callback 函数
- callback 每次执行后的返回值组合起来形成一个新数组
- callback 函数会被自动传入三个参数:数组元素,元素索引,原数组本身
基本用法
let numbers = [1, 5, 10, 15];let roots = numbers.map(function(x) {return x * 2;});
Set类似于数组, 区别是内部成员的值不能重复.
Set是一个构造函数,可以创建Set数据结构.
Set实例的操作数据的方法: add(value), delete(value)
Set实例的遍历方法之一:
forEach()使用回调函数遍历每个成员.
基本用法:
/*使用Set和forEach方法实现数组去重*///创建一个Set的实例sconst s = new Set();//使用forEach遍历数组, 使用add()添加到s里[2, 3, 5, 4, 5, 2, 2].forEach(x => s.add(x));//输出s里的成员变量for (let i of s) {console.log(i);}// 2 3 5 4
Map类似于对象,是键值对的集合, 但是“键”的范围不限于字符串, 各种类型的值(包括对象)都可以当作键.
Map是一个构造函数,可以创建Map数据结构.
Map实例的操作数据的方法: add(value), delete(value), set(value), get(value)
Map实例的遍历方法之一:
forEach()
基本用法:
var map = new Map([ ["name", "张三"], ["title", "Author"]]);map.size // 2map.has("name") // truemap.get("name") // "张三"map.has("title") // truemap.get("title") // "Author"
代码演示(2)
var names = ['Michael', 'Bob', 'Tracy'];var scores = [95, 75, 85];var m = new Map([['Michael', 95], ['Bob', 75], ['Tracy', 85]]);m.get('Michael'); // 95
- 使用 “ 箭头 ”(
=>)定义函数.- 箭头函数不绑定自己的this, arguments, super.
- 箭头函数是匿名函数.
- 不能用作构造函数.
基本语法:
// 无参数的函数需要使用圆括号() => { statements }//等同于function() { statements }
箭头函数 VS 普通函数
//ES6两种写法(i) => i + 1i => i + 1//ES5function(i) {return i + 1;}
有参数和无参数的写法
var f = () => 5;// 等同于var f = function () { return 5 };var sum = (num1, num2) => num1 + num2;// 等同于var sum = function(num1, num2) {return num1 + num2;};
简化回调函数
//普通函数写法[1, 2, 3].map(function (x) {return x * x;});//箭头函数写法[1, 2, 3].map(x => x * x);
代码演示(3)
Symbol 是一种特殊的、不可变的数据类型,可以作为对象属性的标识符使用。
基本数据类型: Undefined、Null、Boolean、Number、String、Symbol.
好处是可以使用在对象属性名,不会被覆盖
基本用法
//创建一个Symbollet s = Symbol();typeof s //symbol//区别不同的symbolvar s1 = Symbol('hello')
//作为属性名的Symbolvar mySymbol = Symbol();// 第一种写法var a = {};a[mySymbol] = 'Hello!';// 第二种写法var a = {[mySymbol]: 'Hello!'};// 第三种写法var a = {};Object.defineProperty(a, mySymbol, { value: 'Hello!' });// 以上写法都得到同样结果a[mySymbol] // "Hello!"
- Promise是一个对象,用来传递异步操作的消息
- 异步操作的三种状态:
Pending(进行中)
Resolved(已完成)
Rejected(已失败)- 同步/异步操作: 案例说明
- 应用场景: Ajax
基本用法:
//创建一个Promise对象的实例,//两个参数都是函数, 分别是resolove和rejectvar promise = new Promise(function(resolve, reject) {// 执行一些操作if (/* 异步操作成功 */){resolve(value);} else {reject(error);}});
代码演示(1)
//应用场景: 回调函数嵌套“金字塔问题”step1(function (value1) {step2(value1, function(value2) {step3(value2, function(value3) {step4(value3, function(value4) {// Do something with value4});});});});//使用promiseQ.fcall(promisedStep1).then(promisedStep2).then(promisedStep3).then(promisedStep4).then(function (value4) {// Do something with value4}).catch(function (error) {// Handle any error from all above steps}).done();
Class和 extends通过class关键字, 可以定义类, 实现类的继承。
基本用法
//ES6使用class定义类class Point {//必须使用consructor构造方法constructor(x, y) {this.x = x;this.y = y;}toString() {return '('+this.x+', '+this.y+')';}}//在ES5中使用原型(prototype)定义类function Point(x,y){this.x = x;this.y = y;}Point.prototype.toString = function () {return '('+this.x+', '+this.y+')';}
Module模块
- 模块功能主要由两个命令构成:export和import。
- export命令用于规定模块的对外接口。
- import命令用于输入其他模块提供的功能。
// profile.js// export关键词可以使外部读取内部的变量export var firstName = 'Michael';export var lastName = 'Jackson';export var year = 1958;//另一种写法var firstName = 'Michael';var lastName = 'Jackson';var year = 1958;export {firstName, lastName, year};
// main.js// import命令可以加载export命令定义的对外接口import {firstName, lastName, year} from './profile';function setName(element) {element.textContent = firstName + ' ' + lastName;}
输出一个匿名函数
// export-default.jsexport default function () {console.log('foo');}
使用import为该匿名函数命名
// import-default.jsimport customName from './export-default';customName(); // 'foo'
案例
创建一个模块
export关键词放在变量声明的前方.使用这个模块
将import放在main.js的第一行.
import * as mortgage from './mortgage';
Build 和 Run
目前各大公司关于ES6相关面试题案例分析.
let name = 'zach'while (true) {let name = 'obama'console.log(name)break}console.log(name)
a. zach zach
b. obama obama
c. zach obama
d. obama zach
var a = [];for (let i = 0; i < 10; i++) {a[i] = function () {console.log(i);};}a[6]();
a. 10
b. 1
c. 6
d. 0
以下代码会输出
var f = ([a, b] = [1, 2], {x: c} = {x: a + b}) => a + b + c;f();
a. 2
b. 5
c. 6
d. 3
'use strict';| ES6特性 | 兼容性 |
|---|---|
| 箭头函数 | 支持 |
| 类的声明和继承 | 部分支持,IE8不支持 |
| 增强的对象字面量 | 支持 |
| 字符串模板 | 支持 |
| 解构 | 支持,但注意使用方式 |
| 参数默认值,不定参数,拓展参数 | 支持 |
| let与const | 支持 |
| for of | IE不支持 |
| iterator, generator | 不支持 |
| 模块 module、Proxies、Symbol | 不支持 |
| Map,Set 和 WeakMap,WeakSet | 不支持 |
| Promises、Math,Number,String,Object 的新API | 不支持 |
| export & import | 支持 |
| 生成器函数 | 不支持 |
| 数组拷贝 | 支持 |
Scratch JS ES6转换ES5,调试ES6代码