typora-copy-images-to: media
ES6
变量声明let与const
-
let声明的变量不存在预解析
console.log(flag); // 会出错而不是undefined let flag = 123;
-
let声明的变量不允许重复(在同一个作用域内)
let flag = 123; let flag = 456; console.log(flag) // 会报错
-
块内部定义的变量,在外部是不可以访问的
ES6中的块:
if(){块}
for(){块}
{块}
if( true ){ let uname = ‘java‘; } console.log(uname); // 报错 ReferenceError: uname is not defined { let age = 13; } console.log(age); // 报错 ReferenceError: age is not defined for (let i = 0; i < 3; i++) { // for循环括号中声明的变量只能在循环体中使用 console.log(i); } console.log(i);
-
在块级作用域内部,变量只能先声明再使用
if(true){ console.log(flag); // 报错 let flag = 123; }
-
const用来声明常量,const不允许重新赋值,const声明的常量必须初始化
变量的解构赋值
-
数组的解构赋值
let [a,b,c] = [1,2,3]; // 1 2 3 let [a,b,c] = [,123,]; // undefined 123 undefined let [a=111,b,c] = [,123,]; // 111 123 undefined console.log(a,b,c);
?
-
对象的解构赋值
// 基础 let {foo,bar} = {foo : ‘hello‘,bar : ‘hi‘}; let {foo,bar} = {bar : ‘hi‘,foo : ‘hello‘}; console.log(foo, bar); // hello hi // 对象属性别名(如果有了别名,那么原来的名字就无效了) let {foo:abc,bar} = {bar : ‘hi‘,foo : ‘nihao‘}; console.log(foo,bar); // 报错 console.log(abc, bar); // 正确 // 对象的解构赋值指定默认值 let {foo:abc=‘hello‘,bar} = {bar : ‘hi‘}; console.log(abc,bar); // hello hi // Math是一个对象,所以也能被解构 let {cos,sin,random} = Math; console.log(typeof cos); console.log(typeof sin); console.log(typeof random);
?
-
字符串的解构赋值
let [a,b,c,d,e] = "hello"; console.log(a,b,c,d,e); // h e l l o let {length} = "hi"; console.log(length); // 2
字符串扩展
-
includes(子字符串, 开始位置) - 判断字符串中是否包含指定的字串(有的话返回true,否则返回false)
-
startsWith(子字符串) - 判断字符串是否以特定的字串开始
-
endsWith(子字符串) - 判断字符串是否以特定的字串结束
-
模板字符串``
// 字符串匹配 console.log(‘hello world‘.includes(‘world‘,7)); // false let url = ‘admin/index.php‘; console.log(url.startsWith(‘aadmin‘)); console.log(url.endsWith(‘phph‘)); // 模板字符串 let obj = { username : ‘lisi‘, age : ‘12‘, gender : ‘male‘ } let fn = function(info){ return info; } let tpl = ` <div> <span>${obj.username}</span> <span>${obj.age}</span> <span>${obj.gender}</span> <span>${1+1}</span> <span>${fn(‘nihao‘)}</span> </div> `; console.log(tpl); // 解析后的html代码
?
函数扩展
-
参数默认值
function foo(param = ‘nihao‘){ console.log(param); } foo(); // nihao foo(‘hello kitty‘); // hello kitty
-
参数解构赋值
function foo({uname=‘lisi‘,age=13}={}){ console.log(uname,age); } foo({uname:‘zhangsan‘,age:15});
-
...rest参数(剩余参数)(位置:形参)
function foo(a,b,...param){ console.log(a); console.log(b); console.log(param); //[3,4,5] } foo(1,2,3,4,5);
?
-
...扩展运算符(位置:实参)
function foo(a,b,c,d,e,f,g){ console.log(a + b + c + d + e + f + g); } // foo(1,2,3,4,5); let arr = [1,2,3,4,5,6,7]; // foo.apply(null,arr); foo(...arr); /* 合并数组 */ let arr1 = [1,2,3]; let arr2 = [4,5,6]; let arr3 = [...arr1,...arr2]; console.log(arr3);
?
-
箭头函数
- 箭头函数中this取决于函数的定义,而不是调用
- 箭头函数不可以new
- 箭头函数不可以使用arguments获取参数列表,可以使用rest参数代替
// -------------------- let foo = () => console.log(‘hello‘); // 等同于 function foo(){ console.log(‘hellio‘); } // --------------------单个参数可以缩写,单行的return 可以省略 let foo = v => v; // 等同于 function foo(v){ return v; } // --------------------多个参数必须用小括号包住 let foo = (a,b) => {let c = 1; console.log(a + b + c);} // 等同于 function foo(a,b) { let c = 1; console.log(a + b + c); } // --------------------匿名函数 arr.forEach((item, index) => { console.log(item, index); }); // 等同于 arr.forEach(function(item, index){ console.log(item, index); });
?
-
类与继承
/* 类的定义 */ class Animal{ // 构造方法 constructor(name){ this.name = name; } // 静态方法(静态方法只能通过类名调用,不可以使用实例对象调用) static showInfo(){ console.log(‘hi‘); } showName(){ console.log(this.name); } } let a = new Animal(‘Tom‘); a.showName(); // 调用类中的方法 Animal.showInfo(); // 调用静态方法 /* 类的继承 */ class Dog extends Animal{ constructor(name, color){ super(name); // 调用父类中的构造方法 this.color = color; } showColor(){ console.log(this.color); } } let d = new Dog(‘jerry‘, ‘red‘); d.showColor(); // 调用自身的方法 d.showName(); // 调用父类的方法 Dog.showInfo(); // 调用父类的静态方法
API
-
find(callback) - 回调查找第一个符合条件的数组元素
- callback 查找的条件,返回一个布尔值
-
findIndex(callback) - 回调查找第一个符合条件的数组元素的索引
- callback 查找的条件,返回一个布尔值
Promise
回调地狱
为了解决以上编码方式带来的问题(回调地狱嵌套),所以在ES6中新增了一个API:Promise
解析Promise
- Promise是一个构造函数
- Promise容器一旦创建,就开始执行里面的代码
- Promise本身不是异步的,它里面的任务才是异步的
/* 入门案例 */
const fs = require(‘fs‘);
// 创建Promise容器
// 1. 给别人一个承诺
console.log(1);
+ let p1 = new Promise(function(resolve, reject){
console.log(2);
fs.readFile(‘data/a.txt‘, ‘utf8‘, function(err, data){
if(err){
//console.log(err);
// 把容器的Pending状态改为 Rejected
+ reject(err);
}else{
console.log(3);
//console.log(data);
// 把容器的Pending状态改为 Resolved
+ resolve(data);
}
});
});
+ let p2 = new Promise(function(resolve, reject){
console.log(2);
fs.readFile(‘data/b.txt‘, ‘utf8‘, function(err, data){
if(err){
//console.log(err);
// 把容器的Pending状态改为 Rejected
+ reject(err);
}else{
console.log(3);
//console.log(data);
// 把容器的Pending状态改为 Resolved
+ resolve(data);
}
});
});
console.log(4);
// p1就是那个承诺的实例对象
// then中的第1个回调函数 对应 resolve(data)
// then中的第2个回调函数 对应 reject(err)
p1
+ .then(function(data){
console.log(data);
// p1读取成功时,当前函数中 return 的结果可以在后面的 then 中的 function 回调函数中接收到,没有return 后面就接收到undefined
// 根据这个原理,我们可以 return 一个Promise对象
// 当return一个Promise对象的时候,后面的then中的第一个回调函数会作为p2的 resolve,第二个回调函数会作为p2的 reject
+ return p2;
+ },function(err){
console.log(‘读取文件失败‘, err);
})
+ .then(function(data){
console.log(data);
+ return p3;
},function(err){
console.log(‘读取文件失败‘, err);
})
// 执行结果
1 2 4 3
封装Promise版的readFile
// 封装
var fs = require(‘fs‘);
function pReadFile(filePath){
return new Promise(function(resolve, reject){
fs.readFile(filePath, ‘utf8‘, function(err, data){
if(err)
reject(err);
else
resolve(data);
});
});
}
// 调用
pReadFile(‘data/a.txt‘).then(function(data){
return pReadFile(‘data/b.txt‘);
}).then(function(data){
return pReadFile(‘data/c.txt‘);
})
Promise的应用场景
- ajax同时查询多个数据表接口时,会出现嵌套情况,此时用Promise可以实现链式结构
封装Promise版的ajax