ECMAScript和JavaScript
历史版本
时间 | ECMA | JS | 解释 |
---|---|---|---|
1996.11 | ES 1.0 | JS稳定 | Netscape将JS提交给ECMA组织,ES正式出现 |
1998.06 | ES 2.0 | ES2正式发布 | |
1999.12 | ES 3.0 | ES3被广泛支持 | |
2007.10 | ES 4.0 | ES4过于激进,被废了 | |
2008.07 | ES 3.1 | 4.0退化为严重缩水版的3.1 因为吵得太厉害,所以ES 3.1代号为Harmony(和谐) |
|
2009.12 | ES 5.0 | ES 5.0正式发布 同时公布了JavaScript.next也就是后来的ES 6.0 |
|
2011.06 | ES 5.1 | ES 5.1成为了ISO国际标准 | |
2013.03 | ES 6.0 | ES 6.0草案定稿 | |
2013.12 | ES 6.0 | ES 6.0草案发布 | |
2015.06 | ES 6.0 | ES 6.0预计发布正式版 JavaScript.next开始指向ES 7.0 |
1.兼容性
2.编译与转换,将ES6编译转换成低版本浏览器支持的JS代码
1.var的缺陷
2.新的关键字
var aBtn = document.getElementByTagName('button');
(function(i){
for(var i = 0; i < aBtn.length; i++){
aBtn.i.onclock = function(){
alert(i);
}
})(i)
}
用let不用闭包来解决以上问题:
var aBtn = document.getElementByTagName('button');
for(var let = 0; i < aBtn.length; i++){
aBtn.i.onclock = function(){
alert(i);
}
}
省略条件
let show = function(){
alert('13')
}
show();
let show = ()=>{
alert('13')
}
function add(a, b){
return a+b
}
add(5,12);
(a, b)=>a+b
1.参数扩展/数组展开
function add(a, b, ...args){
return a+b;
};
add(1,2,3,4,4,6);//函数中的3,4,4,6会传给...args;
let arr = [1,2,3] ...arr//1,2,3
let arr1 = [2,3], arr2 = [e,3];
let arr3=[...arr1, ...arr2]; arr3//2, 3, e, 3
2.默认参数, 参数默认值 function(a, b=2){};
3.解构赋值,直接对多个变量同时赋值,解构赋值条件如下:
使用场景
解构赋值在很多时候可以大大简化代码。例如,交换两个变量x和y的值,可以这么写,不再需要临时变量:
var x=1, y=2;
[x, y] = [y, x]
快速获取当前页面的域名和路径:
var {hostname:domain, pathname:path} = location;
如果一个函数接收一个对象作为参数,那么,可以使用解构直接把对象的属性绑定到变量中。例如,下面的函数可以快速创建一个Date对象:
function buildDate({year, month, day, hour=0, minute=0, second=0}) {
return new Date(year + '-' + month + '-' + day + ' ' + hour + ':' + minute + ':' + second);
}
它的方便之处在于传入的对象只需要year、month和day这三个属性:
buildDate({ year: 2017, month: 1, day: 1 });
// Sun Jan 01 2017 00:00:00 GMT+0800 (CST)
也可以传入hour、minute和second属性:
buildDate({ year: 2017, month: 1, day: 1, hour: 20, minute: 15 });
// Sun Jan 01 2017 20:15:00 GMT+0800 (CST)
新增加了四个函数,分别是:
let arr1 = [12, 23, 15];
let result = arr1.map(item=>item);
alert(result);
let result2 = arr1.reduce((tmp, item, index) => {
if(index != arr1.length-1){
return tmp+item
} else {
return (tmp+item)/arr1.length
}
});
arr1.forEach((item, index) => {
console.log(index + ':' + item)
});
1.多了两个新方法,感觉像是根据正则表达式封装实现的
2.字符串模板
let firstname = 'bill';
let lastname = 'gates';
let name = `${firstname}, ${lastname}`;
ES5中实现面向对象的继承需使用原型链,具体如下:
function Person(props){
this.name = props.name;
this.age = props.age;
}
Person.prototype.getName = function(){
return this.name;
}
function Student(props){
Person.call(this, props);
this.school = props.school;
}
Student.prototype = new Person();
Student.prototype.constructor = Student;
出现class, super, extends等面向对象关键字后,便可以使用类似JAVA的方式实现继承,但是实质上是对原型和原型继承的封装,class等关键字只是语法糖,还是要理解原型和原型链等。使用class等关键字如下:
class User{
constructor(name, pass){
this.name = name
this.pass = pass
}
showName(){
alert(this.name)
}
showPass(){
alert(this.pass)
}
}
class VipUser extends User{
constructor(name, pass, level){
super(name, pass)
this.level = level
}
showLevel(){
alert(this.level)
}
}
let vl = new VipUser('hotsuitor', '123456', 5)
v1.showName()
v1.showPass()
v1.showLevel()
JSON是JavaScript Object Notation的缩写,它是一种数据交换格式,由道格拉斯·克罗克福特(Douglas Crockford)设计,JSON实际上是JavaScript的一个子集。JSON还定死了字符集必须是UTF-8,表示多语言就没有问题了。为了统一解析,JSON的字符串规定必须用双引号”“,Object的键也必须用双引号”“。在JSON中,数据类型:
1.JSON对象,两个方法:
var xm = {
name: '小明',
age: 14,
toJSON: function () {
return { // 只输出name和age,并且改变了key:
'Name': this.name,
'Age': this.age
};
}
};
JSON.stringify(xm);
JSON.parse('{"name":"小明","age":14}'); // Object {name: '小明', age: 14}
2.JSON简写
let a=12,b=12;
let json={a,b,c:12} == {a:a,b:b,c:12}
let json = {
a:12,
show(){
alert(this.a);
}
}
是JS异步编程的重要概念,异步抽象处理对象,是目前比较流行的JS异步编程解决方案之一
异步编程方案有以下几种,具体后面会有文章来详细介绍:
Promise 是一个构造函数, new Promise 返回一个 promise对象 接收一个excutor执行函数作为参数, excutor有两个函数类型形参resolve reject。
promise相当于一个状态,有三种状态,并且promsie状态只能由 pending => fulfilled/rejected, 一旦修改就不能再变:
Promise像是一个状态机,分为初始状态、成功和失败状态。Promoise的构造函数接受一个函数fn作为参数,fn有两个参数函数:参数resolve和reject,因为Promise是一个状态机,需要声明一个属性记录其状态,同时,需要声明两个属性记录返回数据,then方法接受两个函数,分别用来处理返回的成功状态的promise对象和失败状态的对象,但then方法是异步执行的,因此,当运行到then方法时,可能fn还没有执行完毕,因此,需要在constructor中分别声明事件队列用来记录then方法中的两个函数,那么,相应的fn方法中resolve方法需要遍历执行成功事件队列,reject方法需要遍历执行失败事件队列。
class Promise2 {
constructor(fn) {
const _this = this;
_this.status = '';
_this._queue = [];
_this._succ_res = null;
_this._erro_res = null;
fn(function(...arg) {
_this._succ_res = arg;
_this.status = 'success';
_this._queue.forEach(function(json) {
json.fn1(...arg);
});
}, function(...arg) {
_this._erro_res = arg;
_this.status = 'error';
_this._queue.forEach(function(json) {
json.fn2(...arg);
});
});
}
then(fn1, fn2) {
if (this.status === 'success') {
fn1(this._succ_res);
} else if (this.status === 'error') {
fn2(this._erro_res);
} else {
this._queue.push({fn1, fn2});
}
}
}
Promise2.all = function(arr){
let res = [];
return new Promise2(function(resolve, reject){
let i = 0;
next();
function next() {
arr[i].then(function(result){
res.push(result);
i++;
if(i === arr.length){
resolve(res);
}else{
next();
}
},reject);
}
})
};
Promise适用于一次对很多数据情况。
let p1=new Promise(function (resolve, reject){
$.ajax({
url: 'data/arr.txt',
dataType: 'json',
success(arr){
resolve(arr);
},
error(err){
reject(err);
}
})
});
let p2=new Promise(function (resolve, reject){
$.ajax({
url: 'data/json.txt',
dataType: 'json',
success(arr){
resolve(arr);
},
error(err){
reject(err);
}
})
});
Promise.all([
p1, p2
]).then(function (arr){
let [res1, res2]=arr;
alert('全都成功了');
alert(res1);
alert(res2);
}, function (){
alert('至少有一个失败了');
});
生成器对象是由一个 generator function 返回的,并且它符合可迭代协议和迭代器协议。普通函数是一路执行到底,Generator可以中间暂停。
语法如下:
function show(){
alert("a")
alert("b")
}
show(); //一次性执行完整个函数
function *show2(){
alert("a")
yield
alert("b")
}
let geneObj = show2();
show2().next() //alert a
show2().next() //alert b
可以理解为:Generator函数底层实现是把一个“大函数”生成多个yield分割的“小函数”。
let geneObj = show2();
geneObj.next();//第一个参数无效,可以在show()函数中设置参数,show(12);
geneObj.next(12);
理解yield,可以通过下图来理解理解yield。
1.在NodeJS中:
npm install yield-runner-blue //安装blue封装的包
runner(function *(){
let data1 = $.ajax(url, dataType:'json')
let data2 = $.ajax(url, dataType:'json')
let data3 = $.ajax(url, dataType:'json')
console.log(data1, data2, data3)
})
2.异步操作
Generator generator 带逻辑的异步更方便,Promise适合一次读一堆,不适合带逻辑异步操作
Promise.all([
$.ajax({url: xxx, dataType: 'json'})
$.ajax({url: xxx, dataType: 'json'})
$.ajax({url: xxx, dataType: 'json'})
]).then(result=>{
}, error=>{
})
runner(function *(){
let data1 = yield $.ajax({url: xxx, dataType: 'json'})
let data2 = yield $.ajax({url: xxx, dataType: 'json'})
let data3 = yield $.ajax({url: xxx, dataType: 'json'})
});
//带逻辑的 generator
runner(function *(){
let userData = yield $.ajax(url: 'getUserType', dataType: 'json')
if (userData == 'VIP') {
let VipUser = yield $.ajax(url: 'getVipUsers', dataType: 'json')
} else {
let normalUser = yield $.ajax(url: 'getNormalUsers', dataType: 'json')
}
//其他逻辑
})