1.ES5和ES6声明变量的方式对比
ES5中声明变量:var
1可以重复声明
2无法限制修改
3没有块级作用域
ES6中声明变量:let const
let 不能重复声明,变量-可以修改, 块级作用域
const 不能重复声明,常量-不能修改, 块级作用域
对于块级作用域用什么好处,以下举一个例子
//在ES6中没有块级作用域的情况下,以下按钮点击任何一个按钮都只会弹出最后一位
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script type="text/javascript">
window.onload = function (){
var aBtn = document.getElementsByTagName('input');
for(var i=0;i<aBtn.length;i++){
aBtn[i].onclick = function(){
alert(i)
}
}
}
</script>
</head>
<body>
<input type="button" name="" id="" value="按钮1" />
<input type="button" name="" id="" value="按钮2" />
<input type="button" name="" id="" value="按钮3" />
</body>
</html>
//在没有用ES6之前解决办法就是以下处理,利用函数作为一级作用域,不过就是有点麻烦
for(var i=0;i<aBtn.length;i++){
(function(i){
aBtn[i].onclick = function(){
alert(i)
};
})(i);
}
//直接用let的就可以快速解决这类问题
for(let i=0;i<aBtn.length;i++){
(function(i){
aBtn[i].onclick = function(){
alert(i)
};
})(i);
}
2.ES6 中箭头函数
ES6 中函数式声明方式被箭头函数 => 取代
箭头函数:使用 => 定义函数
1.如果只有一个参数,( )可以省
2.如果只有一个return,{ }可以省
//简写前
let show = (a) =>{
return a*2;
};
alert(show(12)); //24
//简写后
let show = a => a*2;
alert(show(12)); //24
//两个参数时()不能省
let show = (a,b) => a+b;
alert(show(1,2)); //3
3.函数的参数
- 参数的扩展/展开
- 默认参数
参数扩展:
1.收集剩余参数
//*Rest Parameter必须是最后一个,也就是以下代码中的args参数
function show(a,b,...args){
alert(args);
}
show(12,14,1,2,3); // a=12 b=14 args=1,2,3
//如果args不是在最后一个,会报错
function show(a,b,...args,c){
alert(args);
}
show(12,14,1,2,3);
//Uncaught SyntaxError: Rest parameter must be last formal parameter
2.展开数组
展开后的效果,跟直接把数组的内容写在这儿一样
let arr1 = [1,2,3];
console.log(arr1); //[1, 2, 3]
console.log(...arr1); //1 2 3
//也可以用在合并两个数组中
let arr2 = [4,5,6];
let arr = [...arr1,...arr2];
console.log(arr); //[1, 2, 3, 4, 5, 6]
//函数中也可以使用
function show(...args){
fn(...args)
}
function fn(a,b){
console.log(a+b);
}
show(1,2); //3
注意,不可以用在赋值上,以下代码就是直接赋值就报以下错误
Uncaught SyntaxError: Unexpected token '...'
let a;
let arr = [1,2,3];
a = ...arr;
console.log(a);
默认参数:
就是有一默认值,可传可不传
$('#div').animate({width: '200px'});
$('#div').animate({width: ''200px},1000);
4.ES6 中解构赋值
- 左右两边结构必须一样
- 右边必须是个东西
- 声明和赋值不能分开(必修在一句话里完成)
let [a,b,c] = [1,2,3];
console.log(a,b,c); //1 2 3
let {e,f,g} = {a:12, c:5, d:22};
console.log(e,f,g); //12 5 22
let [{a1,a2},[n1,n2,n3],num,str] = [{a1:12,b1:5},[12,5,8],8,'kk'];
console.log(a1,a2,n1,n2,n3,num,str);//12 5 12 5 8 8 "kk"
如果结构不一样无法赋值,会报错
let [a,b] = {a:12,b"12};
console.log(a,b);
//Uncaught SyntaxError: Identifier 'a' has already been declared
如果声明跟赋值分开也一样无法赋值,会报错
let [a,b];
[a,b] = [12,22];
console.log(a,b);
//Uncaught SyntaxError: Identifier 'a' has already been declared
5.数组
- map 映射 一个对一个
- reduce 汇总 一堆出来一个
- filter 过滤器
- forEach 循环(迭代)
map
let arr = [12,5,8];
let result = arr.map(item => item*2)
console.log(result); //[24, 10, 16]
let score = [19,85,59,99];
let res = score.map(item => item>=60?'及格':'不及格');
console.log(res); //["不及格", "及格", "不及格", "及格"]
reduce
let arr = [1,2,3,4];
//tmp初始值, 或者计算结束后的返回值。
//item 当前元素
//当前元素的索引
let result = arr.reduce((tmp,item,index) => {
return tmp+item;
})
//一开始 tmp = arr[0] item = arr[1] index = 1
//后面tmp 会等于最后运算的结构,比如代码中是执行tmp+item
//所以第二次tmp = arr[0] + arr[1] = 3 item = arr[2] index = 2
console.log(result); //10
filter
let arr = [1,2,3,4,5,6];
let result = arr.filter(item => {
if(item%3 == 0){
return true;
}else{
return false;
}
})
console.log(result); //[3, 6]
forEach
let arr = [12,15,13,5];
arr.forEach((item,index) => {
console,log(item); //12 15 13 5
})
6.字符串
- 多了两个新发法
startsWith
endsWith - 字符串模板
字符串连接
i.直接把东西塞到字符串里面 ${东西}
ii.可以折行
//startsWith和endsWith用法
let str = 'https://www.baidu.com';
if(str.startsWith('https://')){
console.log('yes') //yes
}else{
console.log('no');
}
let email = '1002111759@qq.com'
if(email.endsWith('@qq.com')){
console.log('yes');
}else{
console.log('no');
}
//字符串连接
let title = '标题';
let content '内容';
let str = `<div>
<h1>${title}</h1>
<p>${content}</p>
</div>`
console.log(str);
7.ES6的面向对象
class关键字、构造器和类分开了
class里面直接加方法
首先先看一下老版的面向对象以及继承
function User(name,pass){
this.name = name;
this.pass = pass;
}
User.prototype.showName = function (){
console.log(this.name);
}
User.prototype.showPass = function (){
console.log(this.pass);
}
var u1 = new User('kk','123456');
u1.showName(); //kk
u1.showPass(); //123456
//老版继承
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 (){
console.log(this.level);
}
var v1 = new VipUser('Flipped','123456',3);
v1.showName(); //Flipped
v1.showPass(); //123456
v1.showLevel(); //3
ES6面向对象新写法
class User{
constructor(name,pass){
this.name = name;
this.pass = pass;
}
showName(){
console.log(this.name);
}
showPass(){
console.log(this.pass)
}
}
var u1 = new User('kk','123456');
u1.showName(); //kk
u1.showPass(); //123456
//ES6继承
class VipUser extends User{
constructor(name,pass,level){
//super指代了整个prototype或者__proto__指向的对象
// 用在构造函数中,必须在使用this之前调用
super(name,pass);
this.level = level;
}
showLevel(){
console.log(this.level);
}
}
var v1 = new VipUser('Flipped','123456',3);
v1.showName(); //Flipped
v1.showPass(); //123456
v1.showLevel(); //3
面向对象应用---React
没学过React可以跳过以下案例
React:
- 组件化 -- class 一个组件就是一个class
- JSX JSX==babel==browser.js
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="react.js" charset="utf-8"></script>
<script src="react-dom.js" charset="utf-8"></script>
<script src="browser.js" charset="utf-8"></script>
<script type="text/babel">
class Item extends React.Component{
constructor(...args){
super(...args);
}
render(){
return <li>{this.props.str}</li>;
}
}
class List extends React.Component{
constructor(...args){
super(...args);
}
render(){
let aItems = this.props.arr.map(a => <Item str={a}></Item >);
//for(let i=0;i<this.props.arr.length;i++){
// aItems.push(<Item str={this.props.arr[i]}></Item >)
//}
return <ul>
{aItems}
</ul>;
}
}
window.onload = function (){
let oDiv = document.getElementById('div1');
ReactDOM.render(
<List arr = { ['Flipped','good'] }></List >,
oDiv;
);
}
</script>
</head>
<body>
<div id="div1">
</div>
</body>
8.JSON
JSON 格式
JavaScript Object Notation 的缩写,是一种用于数据交换的文本格式。JSON 是 JS对象的严格子集。
JSON 的标准写法:
只能用双引号
所有的key都必须用双引号包起来
JSON 对象
JSON 对象是 JavaScript 的原生对象,用来处理 JSON 格式数据,有两个静态方法:
JSON.parse(string) :接受一个 JSON 字符串并将其转换成一个 JavaScript 对象。
JSON.stringify(obj) :接受一个 JavaScript 对象并将其转换为一个 JSON 字符串。
let json={a:12,b:5};
//因为在作用与url当作参数传递的时候,如参数出现空格这样的特殊字段,
//后台只可以读取到空格前的内容,后面内容丢失,造成数据读取失败,
//但是如果用encodeURIComponent()包裹一下,那会将这些特殊字符进行转义,
//这样后台就可以成功读取了,所以encodeURIComponent()用于url作为参数传递的场景中使用
let str='https://www.baidu.com?data='+encodeURIComponent(JSON.stringify(json));
alert(str);
let json={a:12,b:5};
alert(JSON.stringify(json)); //json转字符串
let str = '{"a": 12, "b": 5, "c": "abc"}';
let json1 = JSON.parse(str); //字符串转json
console.log(json1);
let a=12;
let b=5;
let json={a,b,c:55}; //名字和值一样,可以只写一个
console.log(json);
let json={
a:12,
/*show: function () {//旧写法
alert(this.a);
}*/
show() {
alert(this.a);
}
};
json.show();
9.ES6的Promise
promise:为了解决异步编程中的回调地狱而产生
- 异步:操作直接没啥关系,同时进行多个操作,回调嵌套多个就会产生回调地狱
- 同步:同时只能做一件事
基本用法
Promise 对象是由关键字 new 及其构造函数来创建的。
首先,介绍一下如何创建一个 Promise;
// 方法1
let promise = new Promise ( (resolve, reject) => {
if ( success ) {
resolve(res) // pending ——> resolved 参数将传递给对应的回调方法
} else {
reject(err) // pending ——> rejectd
}
} )
// 方法2
function promise () {
return new Promise ( function (resolve, reject) {
if ( success ) {
resolve(res)
} else {
reject(err)
}
} )
}
该构造函数接收两个函数作为参数,分别是resolve和reject。
当异步操作执行成功后,会将异步操作结果作为参数传入resolve函数并执行;失败则会将异步操作的错误作为参数传入reject函数并执行;
然后通过then方法,分别指定resolved状态和rejected状态的回调函数。
promise.then(function(value) {
// 成功
}, function(error) {
// 失败
});
.catch()的作用是捕获Promise的错误,与then()的rejected回调作用几乎一致。但是由于Promise的抛错具有冒泡性质,能够不断传递,这样就能够在下一个catch()中统一处理这些错误。同时catch()也能够捕获then()中抛出的错误,所以建议不要使用then()的rejected回调,而是统一使用catch()来处理错误
promise.then(
(value) => {
//成功
}
).catch(
(err) => {
//失败
}
)
Promise方法
(1) Promise.all()
Promise的all方法提供了并行执行异步操作的能力,并且在所有异步操作执行完后才执行回调。
//如果传入的参数中存在不是Promise实例,则会先调用Promise.resolve,
//将其转为Promise实例,再进一步处理。
var a1 = Promise.resolve('kk');
var a2 = 'is';
var a3 = new Promise((resolve, reject) => {
setTimeout(resolve, 100, 'good');
});
Promise.all([a1, a2, a3]).then(values => {
console.log(values);
});
// ["kk", "is", "good"]
(2) Promise.race()
Promise.race 的使用
race有赛跑之译,因此返回的新实例状态,是跟随参数中最先改变状态的那个实例;如果不是Promise实例,依旧先用Promise.resolve方法,转化后再进一步处理。
如果传的迭代为空,则返回的 Promise 永远等待
var promise1 = new Promise(function(resolve, reject) {
setTimeout(resolve, 100, '第一个请求');
});
var promise2 = new Promise(function(resolve, reject) {
setTimeout(reject, 200, '第二个请求');
});
Promise.race([promise1, promise2]).then(function(value) {
console.log(value);
}, function(err) {
console.log(err);
});
// 第一个请求
(3)Promise.resolve() / Promise.reject()
用来包装一个现有对象,将其转变为Promise对象,但Promise.resolve()会根据参数情况返回不同的Promise:
参数是Promise:原样返回
参数带有then方法:转换为Promise后立即执行then方法
参数不带then方法、不是对象或没有参数:返回resolved状态的Promise
Promise.reject()会直接返回rejected状态的Promise
10.ES6的generator - 生成器
普通函数--一路到底
generator函数--中间能停
function *show(){
alert('a');
yield;//放弃执行的权利,先暂时不往下走
alert('b');
}
let genObj = show();
genObj.next(); //没有next不会执行函数下一步
genObj.next();
yield:可以传参和返回
//yield传参
function *show(){
alert('a');
let a = yield;
alert('b');
alert(a); //5
}
let genObj = show();
genObj.next(12); //没法给yield传参,只执行到yield前面的代码
genObj.next(5);
//yield返回
function *show(){
alert('a');
yield 12;
alert('b');
return 44;//没有return的话res2的value值为undefined
}
let genObj = show();
let res1 = genObj.next();
console.log(res1); //{ done: false, value: 12 }
let res2 = genObj.next();
console.log(res2); //{ done: true, value: 44 }
通俗化就是以下伪代码
function *炒菜(菜市场买回来的){
洗菜 -> 洗好的菜;
let 干净的菜 = yield 洗好的菜;
干净的菜 ->切->丝
let 切好的菜 = yield 丝;
切好的菜->炒->熟的菜
return 熟的菜;
}
ES7 & ES8
1.数组 includes
数组是否包含某个东西
includes()作用,是查找一个值在不在数组里,若是存在则返回true,不存在返回false.
2.数组 keys/values/entries
| 数组 | json | |
|---|---|---|
| for...in | 下标(key) | 下标(key) |
| for...of | 值(value) | 不能用在json |
key => 所有的key拿出来 0,1,2,3
let arr = [12,5,7,99];
for(let key of arr.keys()){
console.log(key) //0 1 2 3
}
values => 所有的values拿出来 12,5,7,99
let arr = [12,5,7,99];
for(let value of arr.values()){
console.log(value) //12,5,7,99
}
entries => 所有的key-value对拿出来 {key:0, value: 12}, {key:1, value: 5}...
let arr = [12,5,7,99];
for(let entry of arr.entries()){
console.log(entry)
}
//{0:0,1: 12} {0:1, 1: 5} {0:2,1:7} {0:3,1:99}
3.幂
console.log(2**2) //4
4.padStart/padEnd
console.log('('+'abc'.padStart(10)+')'); //( abc)
console.log('('+'abc'.padStart(10,'0')+')'); //(0000000abc)
console.log('('+'abc'.padEnd(10)+')'); //(abc )
5.async await
async: 异步的意思。看代码
async function testAsync() {
return "hello async";
}
console.log( testAsync() ) //输出结果是 Promise {<pending>}并不是"hello async"
async 的作用是申明一个异步函数,函数的返回值是promise 对象
即 async 函数返回的是一个 Promise 对象
await
await 是 async+wait 的结合 即异步等待,async和await 二者必须是结合着使用
await 是个运算符,用于组成表达式,await 表达式的运算结果取决于它等的东西。
function getSomething() {
return "something";
}
async function testAsync() {
return Promise.resolve("hello async");
}
async function test() {
const a = await getSomething() // await 后面也可以不是promise对象
const b = await testAsync()
console.log(a, b); // 输出结果是 “something hello async”
}
test()
注意:
如果它等到的不是一个 Promise 对象,那 await 表达式的运算结果就是它等到的东西。
如果它等到的是一个 Promise 对象,await 就忙起来了,它会阻塞后面的代码,等着 Promise 对象 resolve,然后得到 resolve 的值,作为 await 表达式的运算结果。