ES6
现在前端开始已经普遍使用es6进行开发,但是浏览器还不能很好的支持es6语法。
ES6开发环境搭建
1.安装node(https://nodejs.org/zh-cn/)
2.新建项目目录,在该目录路径下运行运行 npm init
3.命令行npm install
4.运行npm install –save-dev babel-cli
5.配置packages.json文件,在scripts中配置 “bulid”:”babel src -d lib”
6.该命令是将src所有使用es6语法的js脚本通过babel编译为浏览器能识别的js脚本,并放在src同级的lib目录中。如果在该目录的命名行中运行 babel+空格+文件路径,就是单独编译该文件,并会在命令行输出,当然也可以配置编译结果的输出目录。具体请看http://babeljs.io/docs/en/babel-cli/
7.当然这样我们就能使用es6,但是在实际开发过程中,这样做会异常麻烦,我们需要配合其他开发工具一起使用,我一般使用webpack,其基本配置可以参考babel官网 (http://babeljs.io/setup.html#installation)
ES6重点语法
- 模块化
import util from './util1.js';
impor {fn1, fn2} from './util2.js';
console.log(util1); // {a: 100}
fn1(); // 1
fn2(); // 2
// util1.js
export default {
a: 100
}
// util2.js
export function fn1 () {
console.log(1);
}
export function fn2 () {
console.log(2);
}
// export 引用时要加上{}
// 一个js文件中可以有多个export
// 一个js文件中只能有一个export default
// babel 编译ES6语法,模块化可用webpack和rollup,期待前端早日实现模块化的统一
- class
// JS构造函数
function MathHandle (x, y) {
this.x = x;
this.y = y;
}
MathHandle.prototype.add = function () {
return this.x + this.y;
}
var m = new MathHandle(1, 2);
console.log(m.add());
// ---------------------------------------------
// ES6
class MathHandle {
constructor (x, y) {
this.x = x;
this.y = y;
}
add () {
return this.x + this.y;
}
}
const m = new MathHandle(1, 2);
console.log(m.add());
typeof MathHandle // function
MathHandle === MathHandle.prototype.consturctor; // true
m.__proto__ === MathHandle.prototype // true
// 实际是语法糖形式,看起来和实际原理不一样,为了和java C#形式上看起来相同,不利于新手了解JavaScript原理
继承
class Animal {
constructor (name) {
this.name = name;
}
eat () {
console.log(`S{this.name} 吃肉`);
}
}
class Dog extends Animal {
constructor (name) {
// super可以当做函数使用,可以当做对象使用,ES6要求子类的构造函数必须执行一次super,super作为对象指向父类的原型,在静态方法中使用指向父类
super(name);
this.name = name;
}
say () {
console.log(`${this.name} say`);
}
}
class Dog = new Dog('哈士奇');
dog.say(); // 哈士奇 say
dog.eat(); // 哈士奇 吃肉
- promise
promise由jQuery中的deferred的对象演化而来,deferred对象是不安全的,执行转态可以在外部通过reslove和reject方法在外部改变deferred详解
// 需引入jQuery
function waitHandle () {
var dtd = $.Deferred();
var wait = function (dtd) {
var task = function () {
console.log("执行完成");
dtd.resolve(); //表示异步任务执行完成
// dtd.reject() 失败只能是一个;
};
setTimeout(task, 2000);
return dtd;
};
return wait(dtd);
}
var w = waitHandle();
w.then(function () {
console.log('ok 1');
}, function () {
console.log('err 1')
}).then(function () {
console.log('ok 2');
}, function () {
console.log('err 2')
});
// 还有w.done w.fail...
w.reject(); // 没有这一句,2s后输出:执行完成,ok 1,ok 2;加上这一句后输出err 1,err 2,2s后输出:执行完成;不同的人合作会造成很大的麻烦
// 为了安全我们需要在返回jquery中的promise对象
function waitHandle () {
var dtd = $.Deferred();
var wait = function (dtd) {
var task = function () {
console.log("执行完成");
dtd.resolve();
// dtd.reject();
};
setTimeout(task, 2000);
return dtd.promise(); //唯一修改的地方,但会promise对象
};
return wait(dtd);
}
var w = waitHandle();
w.then(function () {
console.log('ok 1');
}, function () {
console.log('err 1')
}).then(function () {
console.log('ok 2');
}, function () {
console.log('err 2')
});
w.reject(); // Uncaught TypeError: w.reject is not a function 执行完成 ok 1 ok 2
// 外边只能监听不能改变执行状态
// promise标准的基本语法
// new一个Promise对象,传入一个函数,有两个参数resolve,reject,最后返回promise对象实例
function loadImg (src) {
var promise = new Promise(function (resolve, reject) {
var img = document.createElement('img');
img.onload = function () {
resolve(img);
}
img.onerror = function () {
reject()
}
img.src = src;
});
return promise;
}
var src = "http://www.imooc.com/static/img/index/logo_new.png";
var result = loadImg(src);
result.then(function (img) {
console.log(img.width);
return img;
}, function () {
console.log("失败");
}).then(function (img) {
console.log(img.height);
});
// 异常捕获 成功只传入成功后执行的函数,一个函数
var src = "http://www.imooc.com/static/img/index/logo_new.png";
var result = loadImg(src);
// var result1 = loadImg(src);
result.then(result.then(function (img) {
console.log(img.width);
return img;
// return result1;就可以实现多个promise串联执行
}).then(function (img) {
console.log(img.height);
}).catch(function () {
console.log("fail");
});
// 多个promise全部完成后执行 Promise.all([result, result1,...], function(){}),其中一个Promise完成就执行,promise.race([result, result1,...], function(){})
- let、const
// JS 只能通过var定义变量
var i = 10;
i = 100;
var j = 20;
j = 100;
// ES6
// const 定义常量,定义的量不能改变值
let i = 10;
i = 100;
const j = 20;
j = 200; // 报错
- 多行字符串、模板变量
// JS
var name = 'zhangsan', age = 20, html = '';
html += '<div>';
html += ' <p>' + name + '</p>';
html += ' <p>' + age + '</p>';
html += '</div>'
// 前面写起来复杂,用ES6就简单的多不容易出错,效果一样
let name = 'zhangsan', age = 20;
let html = `<div>
<p>${name}</p>
<p>${age}</p>
</div>`;
- 解构赋值
// JS
var obj = {a: 100, b: 200};
var a = obj.a, b = obj.b;
var arr = ['xx', 'yy', 'zz'];
var x = arr[0];
// ES6
let obj = {a: 100, b: 200};
let {a, b} = obj; // a = 100, b = 200
let {c} = obj // c为undefined 对象解构,变量名和对象属性名对应
let arr = ['xx', 'yy', 'zz'];
let [x, y, z] = arr; // x = 'xx'...
let [m] = arr // m = 'xx' 数组解构,按照数组中的索引与变量一一对应
- 块级作用域
// JS没有块级作用域,所以要注意,写var item 要放在方面
var obj = {a: 100, b: 200};
for (var item in obj) {
console.log(item); // a, b
}
console.log(item); // b
// ES6
const obj = {a: 100, b: 200};
for (let item in obj) {
console.log(item); // a, b
}
console.log(item); // undifined
- 函数默认参数
// JS
function (a, b) {
if (b == null) {
b = 0;
}
}
// ES6
function (a, b = 0) {
}
// 这两者效果相同
- 箭头函数
// JS
var arr = [1, 2, 3];
arr.map(function (item) {
return item + 1;
});
// ES6
const arr = [1, 2, 3];
arr.map(item => item + 1); // 只有一个参数,函数体只有一行,会默认返回
arr.map((item, index) => {
console.log(index);
return item + 1;
});
箭头函数是普通js的补充,箭头函数中的this指向的是函数体之外的最新的js
function fn () {
console.log('real', this); // {a: 100}
var arr = [1, 2, 3];
// JS
arr.map(function (item) {
console.log('js', this); // window对象
return item + 1;
});
// 箭头函数
arr.map(item => {
console.log('es6', this); // {a: 100}
return item + 1;
});
}
fn.call({a: 100});
- es7中的async/await
es7中的async/await是promise的扩展,是最直接的同步写法,then只是将callback拆分了
// promise的写法,waitHandle就是promise中的函数
var w = waitHandle();
w.then(function () {
console.log('ok 1');
}, function () {
console.log(err);
});
// async 和 await写法,想要在函数体中使用await,函数必须使用async标识,await后面必须跟一个promise实例,需要用babel-polyfill
const load = async function () {
const result1 = await loadImg(src1);
console.log(result1);
const result1 = await loadImg(src2);
console.log(result2);
}
load();
// async 和 await使用了promise,可以使用完全同步的写法
// promise 和 async/await改变不了JS单线程的本质