ECMAScript约等于JS
ES6(ES2015)
兼容性:IE10+、Chrome、FireFox、 移动端,、NodeJS
编译、转换
1、在线转换(引入一个库来转换,每次打开页面都会先进行转换)(不好)
babel==browser.js
<script src="browser.js"></script>
<script type="text/babel">
let a=12; let b =15;
</script>
2、提前编译
ES6的修改:变量 函数 数组 字符串 面向对象 Promise generator 模块化
一、变量
ES5的变量:var
1、可以重复声明(没有报错 没有警告)
var a=12; var a=5; console.log(a);//5
2、无法限制修改(没有常量概念)
3、没有块级作用域
{
语法块 (块级作用域)
}
if(){
var a=1;
}
alert(a);// 仍然可以使用
(JS有函数作用域,函数作用域和块级作用域不一样)
ES6的变量:
let(变量,可以修改) const(常量,不能修改)
1、不能重复声明(重复之后会报错)
2、不能变量提升
变量提升:即变量可以在声明之前使用,值为undefined
3、let、const都有块级作用域(块级作用域就是{})
let a=12; a=5; alert(a);//结果是5
const a=12; a=5; //报错
块级作用域和闭包:
var btns=document.getElementByTagName('button');
for(vat i=0;i<3;i++){
btns[i].οnclick=function(){
alert(i);//全是3
}
}
闭包解决:匿名函数,利用函数的作用域
for(vat i=0;i<3;i++){
(function(i){
btns[i].οnclick=function(){
alert(i);
}
})(i)
}
ES6块级作用域解决:
var btns=document.getElementByTagName('button');
for(let i=0;i<3;i++){
btns[i].οnclick=function(){
alert(i);
}
}
二、箭头函数
1、如果只有一个参数,()可以省略
2、函数体内只有一句return,{}和return可以省略
3、修正this:函数体内的this
对象,就是定义时所在的对象,而不是使用时所在的对象
不可以使用yield
命令,因此箭头函数不能用作 Generator 函数。
function去了括号后面加箭头
window.οnlοad=function(){}
箭头函数:window.οnlοad=()=>{}
let show=function(a,b){
alert(a+b);
}
箭头函数:let show=(a,b)=>{
alert(a+b);
}
let arr=[123,234,23,234,2112,23,4,32,1,2,3];
arr.sort(function(a,b){
return a-b
})
箭头函数:arr.sort((a,b)=>{
return a-b
})
let show=function(a){
}
箭头函数:let show=a=>{}
let show=function(a){
return a;
}
箭头函数:let show=a=>return a;
三、函数的参数
1、参数扩展/展开
收集参数:剩余参数rest parameter:三个点,后面名字随便取。必须放在最后。
展开数组:展开后的效果直接把数组的内容拿出来一样(...数组名)
2、默认参数
参数扩展
function show(a,b,...args){ 三个点,后面名字随便取
后面的名字是个数组
alert(args);//[3,4,5,6]
}
show(1,2,3,4,5,6,)
参数展开
let arr=[1,2,3];
console.log(...arr)===console.log(1,2,3)相当于把数组的内容拿出来
let arr1=[1,2,3,];
let arr2=[5,6,7];
let arr=[...arr1,...arr2];
function show(...args){先收集
fn(...args);再展开
}
function fn(a,b)[
alert(a+b);
}
show(12,5);
默认参数
function show(a,b=5,c=12){
alert(b);//5
}
show(12) 如果不传就按默认的,如果传了就是传的参数
四、解构赋值
1、左右两边结构必须一样
2、右边必须存在(不能语法错误,如{12,5},既不是json,又不是数组)
3、声明和赋值不能分开,必须在一句话里
let arr=[1,2,3]
let a=arr[0];
let b=arr[1];
let c=arr[2];
解构赋值:let [a,b,c]=[1,2,3]
let {a,c,d}={a:12,c:5,d:6}
console.log(a,c,d)//12,5,6
let [{a,b},[n1,n2,n3],num,string]=[{a:12,b:5},[12,5,8],8,'exsk'];
let [json,array,num,string]=[{a:12,b:5},[12,5,8],8,'exsk'];
console.log(json);//{a:12,b:5}
左右结构要一样
let [a,b]={a:12,b:5};错 左边是数组,右边是json
声明和赋值不能分开写
let [a,b];
[a,b]=[1,2]; 错,解构赋值缺乏初始化
五、数组
1、map映射 一个对一个 给10个 返回10个
2、reduce汇总 一堆出来一个
3、filter过滤器
4、forEach循环
map
let arr=[12,5,8];
let resulet=arr.map(function(item){
return item*2;
})
console.log(resulet);//[24,10,16]
简写:箭头函数:一个参数可以省略(),只有一个return语句可以省略{}和return
let resulet=arr.map(item=>item*2);
let score=[19,85,99,25,90];
score.map(item=>item>=60?'及格':‘不及格’);
reduce
let arr=[12,69,180,8763];
let result=arr.reduce(function(temp,item,index){
return tmp+item;
})
console.log(result);//arr的和
算平均数
这块使用This必须用箭头函数
let result=arr.reduce((tmp,item,index)=>{
if(index!=this.length-1){
return tmp+item;
} else{
return (tmp+item)/this.length;
}
})
filter
let arr=[12,23,45,34,54,34]
let result=arr.filter(item=>false) 筛选结果全删除
let result=arr.filter(item=>{
if(item%3==0){
return true;
}else{
return false;
}
}) 筛选出能被三整除的
直接可以写成:let result=arr.filter(item=>item%3==0)
var arr=[{title:"包",price:100},{title:"鞋",price:200},{title:"袜子",price:10}]
let result=arr.filter(json=>json.price>100);
forEach
arr=[12,23,43,234,323,34,23,34];
arr.forEach((item,index)=>{
})
六、字符串
1、多了两个新方法
startsWith是否是以“”开头的
endsWith
2、字符串模版`` 可以直接把变量放进去,可以折行
曾经都是单引号、双引号连接
startsWith
let str="asdsdqwe"
str.startsWith("asd");是否是以“asd”开头的
endsWith同理
字符串模版
let a=12;
let str=`a${a}bc`; 输出是a12bc
以前拼接:
let title="标题";
let content="内容";
let str='<div>\
<h1>'+title+'</h1>\
<p>'+content+'</p>\
</div>'
字符串模版:可以折行
let str2=`<div><h1>${title}</h1><p>${content}</p></div>`;
七、面向对象
ES6:
1、class关键字,专门的构造器,构造器和类分开了
2、class里面直接定义方法,不用写在外面了
3、继承 class 子类 extends 父类 继承属性:super(属性名) 方法自动继承
es5面向对象:
function User(name,pass){
this.name=name;
this.pass=pass;
}
User.protptype.showName=function(){
alert(this.name);
}
var u1=new User('blue','123456');
u1.showName();
问题:类和构造函数是一个东西,定义这个类的方法必须用原型定义
ES6面向对象:
class User{
constructor(name,pass){
this.name=name;
this.pass=pass;
}
showName(){
alert(this.pass);
}
}
var u1=new User('blue','123456');
u1.showName();
es5继承:call()
function VipUser(name,pass,level){
User.call(this,name,pass);//继承属性
this.level=level;
}
继承方法:
VipUser.prototype=new User();
VipUser.prototype.constructor=VipUser.;
VipUser.prototype.showLevel=function(){
alert(this.level);
}
es6继承:
class VipUser extends User{
constructor(name,pass,level){
super---超类==父类
super(name,pass); 父类的属性
this.level=level;//自己的属性
}
方法只需要加新的方法即可
showLevel(){
alert(this.level);
}
}
七、面向对象应用——React
1、组件化
2、jsx==babel==browser.js
class Test extends React.Component{
constructor(...args){
super(...args);
}
render(){
return <span>123</span>;
}
}
八、JSON
json的标准写法:1、只能用双引号(字符串用双引号引起来),2、所有的名字都必须用双引号包起来
1、JSON对象
JSON.stringify(json); JSON对象转字符串
JSON.parse(str); 字符串转JSON对象
2、简写
名字一样时(key和value),可以简写,留一个就行
方法,可以省略:function
JSON对象
let json={a:12,b:5};
let str=JSON.stringify(json);
如果想加到url里面还有加上:encodeURIComponent(str);
let str=‘{a:2,b:3}’;
JSON.parse(str); 报错 因为a和b没有加双引号
let str=‘{“a”:2,"b":3,“c”:"asd"}’;
JSON.parse(str); 正确
简写:
名字和值一样时,可以简写
let a=12;
let b=5;
let json={a:a,b:b};
可以简写为:let json={a,b};
方法
let json={
a:!2,
show:function(){
alert(this.a);
}
}
简写:
let json={
a:!2,
show(){
alert(this.a);
}
}
九、promise
Promise最大的好处是在异步执行的流程中,把执行代码和处理结果的代码清晰地分离了:
消除异步操作:用同步一样的方式,来书写异步代码
promise:像同步一样写东西很简单,但是像异步一样请求,同时进行多个操作
异步:操作之间无关,同时进行多个操作,缺点:会让代码更复杂
同步:同时只能做一件事。优点:代码更简单
ajax:异步请求
有了promise之后的异步,Promise.all([$.ajax(),$.ajax()]).then(res=>{全成功},err=>{只有一个不成功就不成功})
Promise.race 不常用 只要有一个成功就算成功
let p= new Promise(function(resolve,reject){})
p.then(function(){return p1},function(){}).catch(function(){})
catch是直接处理失败,p.then接第一个, .catch接第二个
promise不是直接的请求,是一个对象。是把ajax请求封装在了promise里面
p.then()返回的还是一个promise对象
传统的异步编程会带来的一些问题,
1.序列化异步操作导致的问题:
1),延续传递风格Continuation Passing Style (CPS)
2),深度嵌套
3),回调地狱
2.并行异步操作的困难
// Demonstrates nesting, CPS, 'callback hell'
$.get('api1/data', function(resp1) {
// Next that depended on the first response.
$.get('api2/data', function(resp2) {
// Next request that depended on the second response.
$.get('api3/data', function(resp3) {
// Next request that depended on the third response.
$.get(); // ... you get the idea.
});
});
});
当回调越来越多,嵌套越深,代码可读性就会越来越差。如果注册了多个回调,那更是一场噩梦!
promise提供了一种更简洁和清晰的方式来表示javascript中的顺序异步操作。它们实际上是实现与回调相同效果的不同语法。其优点是增加了可读性。就像这样
aAsync()
.then(bAsync)
.then(cAsync)
.done(finish);
比将每个单独的函数作为回调传递的可读性要高得多,如
Async(function(){
return bAsync(function(){
return cAsync(function(){
finish()
})
})
});
使用:
let p1=new Promise(function(resolve,rejsct){
//resolve成功
//reject失败
//封装一个ajax
$.ajax({
url:"arr1.txt",
dataType:'json',
success(arr){ json简写
resolve(arr)
},
error(err){
reject(err);
}
})
})
p.then(function(arr){
alert('成功了');
console.log(arr);
},function(err){
alert(‘失败了’)
console.log(err)
});
let p2=new Promise(function(resolve,rejsct){
$.ajax({
url:"arr2.txt",
dataType:'json',
success(arr){ json简写
resolve(arr)
},
error(err){
reject(err);
}
})
})
Promise.all([
p1,p2
]).then(function(arr){
alert('两个全都成功')
console.log(arr); arr装的是两个结果
let [arr1,arr2]=arr; // 解构赋值
},function(err){
alert('至少有一个失败')
})
可以直接把创建p实例封装:
function createPromise(url){
return
new Promise(function(resolve,rejsct){
$.ajax({
url,
dataType:'json',
success(arr){ json简写
resolve(arr)
},
error(err){
reject(err);
}
})
})
}
Promise.all([
createPromise('arr1.txt'),
createPromise('arr2.txt')
]).then(function(arr){
alert('两个全都成功')
console.log(arr); arr装的是两个结果
let [arr1,arr2]=arr; // 解构赋值
},function(err){
alert('至少有一个失败')
})
jquery高版本本身自带promise
let p=$.ajax({url:'arr.txt',dataType:'json'});
console.log(p); p是一个promise对象
Promise.all([
$.ajax({url:'arr1.txt',dataType:'json'}),
$.ajax({url:'arr2.txt',dataType:'json'}),
]).then(function(res){
let [arr1,arr2]=res;
},function(err){
})
// 0.5秒后返回input*input的计算结果:
function multiply(input) {
return new Promise(function (resolve, reject) {
log('calculating ' + input + ' x ' + input + '...');
setTimeout(resolve, 500, input * input);
});
}
// 0.5秒后返回input+input的计算结果:
function add(input) {
return new Promise(function (resolve, reject) {
log('calculating ' + input + ' + ' + input + '...');
setTimeout(resolve, 500, input + input);
});
}
var p = new Promise(function (resolve, reject) {
log('start new Promise...');
resolve(123);
});
p.then(multiply)
.then(add)
.then(multiply)
.then(add)
.then(function (result) {
log('Got value: ' + result);
});
p.then((val) => console.log('fulfilled:', val))
.catch((err) => console.log('rejected', err));
// 等同于
p.then((val) => console.log('fulfilled:', val))
.then(null, (err) => console.log("rejected:", err));
原来then里面的函数就跟我们平时的回调函数一个意思,能够在runAsync这个异步任务执行完成之后被执行。这就是Promise的作用了,简单来讲,就是能把原来的回调写法分离出来,在异步操作执行完后,用链式调用的方式执行回调函数。
你可能会不屑一顾,那么牛逼轰轰的Promise就这点能耐?我把回调函数封装一下,给runAsync传进去不也一样吗,就像这样:
function runAsync(callback){
setTimeout(function(){
console.log('执行完成');
callback('随便什么数据');
}, 2000);
}
runAsync(function(data){
console.log(data);
});
效果也是一样的,还费劲用Promise干嘛。那么问题来了,有多层回调该怎么办?如果callback也是一个异步操作,而且执行完后也需要有相应的回调函数,该怎么办呢?总不能再定义一个callback2,然后给callback传进去吧。而Promise的优势在于,可以在then方法中继续写Promise对象并返回,然后继续调用then来进行回调操作。
runAsync1()
.then(function(data){
console.log(data);
return runAsync2();
})
.then(function(data){
console.log(data);
return '直接返回数据'; //这里直接返回数据
})
.then(function(data){
console.log(data);
});
https://www.cnblogs.com/lvdabao/p/es6-promise-1.html
Deffered 和 Promise
ES6 和 jQuery 都有 Deffered 和 Promise,但是略有不同。不过它们的作用可以简单的用两句话来描述
-
Deffered 触发 resolve 或 reject
-
Promise 中申明 resolve 或 reject 后应该做什么(回调)
jquery中:
var deferred = $.Deferred();
var promise = deferred.promise();
ES6中:
var deferred = Promise.defer();
var promise= defered.promise;
jQuery 的 Deferred/Promise
jQuery 中最常用的 Promise 对象是 $.ajax()
返回的,最常用的方法不是 then
,而是 done
、fail
和 always
。除了 $.ajax()
外,jQuery 也提供了 $.get()
、$.post()
和 $.getJSON()
等简化 Ajax 调用,它们返回的和 $.ajax()
的返回值一样,是个 Promise 对象。
实际上
$.ajax()
返回的是一个 jqXHR 对象。但 jqXHR 实现了 jQuery 的 Promise 接口,所以也是一个 Promise 对象。
done()
、fail()
和 always()
done()
添加 deferred.resolve()
的回调,fail()
添加 deferred.reject()
的回调。所以在 Ajax 调用成功的情况下执行 done()
添加的回调,调用失败时执行 fail()
添加的回调。但不管成功与否,都会执行 always()
添加的回调。
这里 done()
、fail()
和 always()
都是以类似事件的方式添加回调,也就意味着,不管执行多次次 done()
、fail()
或 always()
,它们添加的若干回调都会在符合的条件下依次执行。
一般情况下会这样执行 Ajax
十、generator
不能用箭头函数,一般配合yield-runner-blue一起使用
解决异步操作(和promise相像,promise不适合带逻辑的,适合一次读一堆,比如说请求的结果要进行判断再请求下一个接口,generator适合带逻辑的异步操作,因为generator有返回,promise没有返回)
是一种中间能暂停的函数
在普通函数定义的时候加一个* *号位置随意,要配合yield使用在哪暂停
yeild既可以传参,又可以返回中间结果
function *show()
function* show()
function * show()
function *show(){
alert("a");
yield;
alert("b");
}
let geneObj=show();
geneObj.next();//出现a
geneObj.next();//出现b
为什么需要暂停:请求数据,需要时间,之前的解决方法就是在请求成功后的回调函数中写代码,现在就可以用yeild暂停,等请求成功之后再执行后面的代码
原理:用generator生成了两个小函数 yeild前面一个函数,后面一个函数
function *show(){
alert("a");
let a=yield;
alert("b");
alert(a); // 弹出5
}
let geneObj=show();
geneObj.next(12);
geneObj.next(5);
结果:a b 5
第一个geneObj.next(12);执行的是从开始到yield(没有let a =)
第二个geneObj.next(5);执行的是从let a =到结束
所以用geneObj.next();传参是传给yield后面的过程传
返回中间结果:
function *show(){
alert("a");
yield 12;
alert("b");
}
let geneObj=show();
let res1=gen.next();//结果是json对象{value:12,done:false} done表示是否完成
let res2=gen.next();//结果是{value:undefined,donw:true} 最后一个返回得靠return
实例:
cnpm install yield-runner-blue
引入runner.js 和jquery.js
//给runner传入一个generator对象
runner(function *(){
在里面可以像用同步操作来写异步操作
let data1=yiele $.ajax({url:'data/1.txt',dataType:'json'});
let data2=yiele $.ajax({url:'data/2.txt',dataType:'json'});
let data3=yiele $.ajax({url:'data/3.txt',dataType:'json'});
console.log(data1,data2,data3)
})
就可以直接输出结果
异步操作:
1、回调函数
2、promise
Promise.all([
$.ajax({url:"1.txt",dataType:’json'});
$.ajax({url:"2.txt",dataType:’json'});
$.ajax({url:"3.txt",dataType:’json'});
]).then(res=>{全部成功才算成功},res=>{一个失败就算失败})
3、generator
用runner
runner(function *(){
let data1=yield $.ajax({url:"1.txt",dataType:’json'});
let data2=yield $.ajax({url:"2.txt",dataType:’json'});
let data3=yield $.ajax({url:"3.txt",dataType:’json'});
})
generator的优点:前面的请求的结果可以作为后面请求的输入
带逻辑的Promise:(和普通回调一样)
Promise.all([
$.ajax({url:"1.txt",dataType:’json'});
]).then(res=>{
let userData=results[0];
if(userData=='VIP'){
Promise.all([
$.ajax({url:"2.txt",dataType:’json'});
]).then(function(){},function(){})
}
},res=>{一个失败就算失败})
带逻辑的generator:
runner(function *(){
let userData=yield $.ajax({url:"1.txt",dataType:’json'});
if(userData=='VIP'){
let data2=yield $.ajax({url:"2.txt",dataType:’json'});
}else{
let data3=yield $.ajax({url:"3.txt",dataType:’json'});
}
})
实例:KOA
nodejs的框架
cnpm i koa