文章为本人在学习ES6过程中所做笔记,仅用于学习交流。
ES6是啥?
ES6 是 JavaScript 语言的下一代标准,使得 JavaScript 语言可以用来编写复杂的大型应用程序,成为企业级开发语言。
ES6:全称ECMAScript 6.0
ECMAScript 是JavaScript语言的国际标准,JavaScript是ECMAScript的实现。
ES6经过持续几年的磨砺,它已成为 JS 有史以来最实质的升级,特性涵盖范围甚广, 小到受欢迎的语法糖,例如箭头函数(arrow functions)和简单的字符串插值(string interpolation),大到烧脑的新概念,例如代理(proxies)和生成器(generators);它将彻底改变程序员们编写JS代码的方式。
目录
1. this 是静态的. this 始终指向函数声明时所在作用域下的 this 的值
1. 形参初始值 具有默认值的参数, 一般位置要靠后(潜规则)
1.异步编程 纯回调函数 node fs ajax mongodb
2.iterator.next(参数)//参数是上一个返回参数
1.let
let 和var的区别 var全局有效
1) 不允许重复声明
2) 块儿级作用域
3) 不存在变量提升
这样写会报错
console.log(song);
let song = '恋爱达人';
but var
命令会发生“变量提升”
ES6 明确规定,如果区块中存在let和const命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。
var tmp = 123;
if (true) {
tmp = 'abc'; // ReferenceError
let tmp;
console.log(tmp);
}
在let命令声明变量tmp之前,都属于变量tmp的“死区”。
ES6 的块级作用域必须有大括号,如果没有大括号,JavaScript 引擎就认为不存在块级作用域。
// 第一种写法,报错
if (true) let x = 1;
// 第二种写法,不报错
if (true) {
let x = 1;
}
定义函数也是得有大括号
2.const
声明常量一般得大写 必须得赋初值
对于数组和对象的元素修改, 不算做对常量的修改, 不会报错
const TEAM = ['UZI','MXLG','Ming','Letme'];
TEAM.push('Meiko');
可以理解为:
TEAM
储存的是一个地址
3.ES6 解构赋值
ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构
(Destructuring)。
let a = 1;
let b = 2;
let c = 3;
//等价写法
let [a, b, c] = [1, 2, 3];
“模式匹配”
let [foo, [[bar], baz]] = [1, [[2], 3]];
foo // 1
bar // 2
baz // 3
let [ , , third] = ["foo", "bar", "baz"];
third // "baz"
let [x, , y] = [1, 2, 3];
x // 1
y // 3
let [head, ...tail] = [1, 2, 3, 4];
head // 1
tail // [2, 3, 4]
let [x, y, ...z] = ['a'];
x // "a"
y // undefined
z // []
解构赋值
允许指定默认值
。
let [x = 1] = [undefined];
x // 1
let [x = 1] = [null];
x // null
默认值可以引用解构赋值的其他变量,但该变量必须已经声明。
let [x = 1, y = x] = []; // x=1; y=1
let [x = 1, y = x] = [2]; // x=2; y=2
let [x = 1, y = x] = [1, 2]; // x=1; y=2
let [x = y, y = 1] = []; // ReferenceError: y is not defined
1. 数组的结构
const F4 = ['小沈阳','刘能','赵四','宋小宝'];
let [xiao, liu, zhao, song] = F4;
console.log(xiao);
console.log(liu);
console.log(zhao);
console.log(song);
2. 对象的解构
const zhao = {
name: '赵本山',
age: '不详',
xiaopin: function(){
console.log("我可以演小品");
}
};
let {name, age, xiaopin} = zhao;
console.log(name);
console.log(age);
console.log(xiaopin);
xiaopin();
//或者这样直接写
let {xiaopin} = zhao;
xiaopin();
4.模板字符串
1. 声明
反引号:英文下敲两下ESC下面的键
let str = `我也是一个字符串哦!`;
2. 内容中可以直接出现换行符
let str = `<ul>
<li>沈腾</li>
<li>玛丽</li>
<li>魏翔</li>
<li>艾伦</li>
</ul>`;
3. 变量拼接
`${lovest}很厉害`
let lovest = '魏翔';
let out = `${lovest}是我心目中最搞笑的演员!!`;
console.log(out);
5.对象的简化写法
如果变量名和属性名一样的话 可以只写属性名
let name = '尚硅谷';
let change = function(){
console.log('我们可以改变你!!');
}
const school = {
name,
change,
improve(){
console.log("我们可以提高你的技能");
}
}
6.箭头函数
//声明一个函数
let fn = function(){
}
let fn = (a,b) => {
return a + b;
}
调用函数
let result = fn(1, 2);
console.log(result);
1. this 是静态的. this 始终指向函数声明时所在作用域下的 this 的值
而普通函数 this是调用它的
//call 方法调用 可以给参数
2. 不能作为构造实例化对象
let Person = (name, age) => {
this.name = name;
this.age = age;
}
let me = new Person('xiao',30);
console.log(me);
3. 不能使用 arguments 变量
arguments作用:获取参数值
let fn = () => {
console.log(arguments);
}
fn(1,2,3);
4.箭头函数的简写
1) 省略小括号, 当形参有且只有一个的时候
2) 省略花括号, 当代码体只有一条语句的时候, 此时 return 必须省略
而且语句的执行结果就是函数的返回值
let pow = n => n * n;
7.参数默认值
1. 形参初始值 具有默认值的参数, 一般位置要靠后(潜规则)
function add(a,b,c=10) {
return a + b + c;
}
let result = add(1,2);
console.log(result);
2. 与解构赋值结合
function connect({host="127.0.0.1", username,password, port}){
console.log(host)
console.log(username)
console.log(password)
console.log(port)
}
connect({
host: 'atguigu.com',
username: 'root',
password: 'root',
port: 3306
})
8.rest参数
格式:...args
//ES6 引入 rest 参数,用于获取函数的实参,用来代替 arguments
//ES5 获取实参的方式
function date(){
console.log(arguments);
}
date('白芷','阿娇','思慧');
rest 参数
function date(...args){
console.log(args);// filter some every map
}
date('阿娇','柏芝','思慧');
rest 参数必须要放到参数最后
function fn(a,b,...args){
console.log(a);
console.log(b);
console.log(args);
}
fn(1,2,3,4,5,6);
9.扩展运算符
1. 数组的合并
const kuaizi = ['王太利','肖央'];
const fenghuang = ['曾毅','玲花'];
// const zuixuanxiaopingguo = kuaizi.concat(fenghuang);
const zuixuanxiaopingguo = [...kuaizi, ...fenghuang];
console.log(zuixuanxiaopingguo);
2. 数组的克隆
const sanzhihua = ['E','G','M'];
const sanyecao = [...sanzhihua];// ['E','G','M']
console.log(sanyecao);
3. 将伪数组转为真正的数组
const divs = document.querySelectorAll('div');
const divArr = [...divs];
console.log(divArr);// arguments
10.Symbol
表示独一无二的值。
它是 JavaScript 语言的第七种数据类型,前六种是: undefined 、 null 、布尔值(Boolean)、字符串(String)、数值(Number)、对象(Object)。
1.创建Symbol (函数方法)
let s = Symbol();
// console.log(s, typeof s);
let s2 = Symbol('尚硅谷');
let s3 = Symbol('尚硅谷');
2.Symbol.for 创建(对象方法)
let s4 = Symbol.for('尚硅谷');
let s5 = Symbol.for('尚硅谷');
3.例子
let youxi = {
name:"狼人杀",
[Symbol('say')]: function(){
console.log("我可以发言")
},
[Symbol('zibao')]: function(){
console.log('我可以自爆');
}
}
4.内置属性
魔法方法: 它们会在特定的场 景下自动执行
class Person{
static [Symbol.hasInstance](param){
console.log(param);
console.log("我被用来检测类型了");
return false;
}
}
let o = {};
console.log(o instanceof Person);
const arr = [1,2,3];
const arr2 = [4,5,6];
arr2[Symbol.isConcatSpreadable] = false;
console.log(arr.concat(arr2));
具体看文档吧
11.迭代器
通俗理解 就是个遍历
//声明一个数组
const xiyou = ['唐僧','孙悟空','猪八戒','沙僧'];
console.log(xiyou);
//使用 for...of 遍历数组
for(let v of xiyou){
console.log(v);
}
看数组它有这个方法 所以可以用
let iterator = xiyou[Symbol.iterator]();
//调用对象的next方法
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
原理:
//声明一个对象
const banji = {
name: "终极一班",
stus: [
'xiaoming',
'xiaoning',
'xiaotian',
'knight'
],
[Symbol.iterator]() {
//索引变量
let index = 0;
//
let _this = this;
return {
next: function () {
if (index < _this.stus.length) {
const result = { value: _this.stus[index], done: false };
//下标自增
index++;
//返回结果
return result;
}else{
return {value: undefined, done: true};
}
}
};
}
}
//遍历这个对象
for (let v of banji) {
console.log(v);
}
12.生成器
生成器其实就是一个特殊的函数:加个 * 而已啦
function * gen()
1.异步编程 纯回调函数 node fs ajax mongodb
2.函数代码的分隔符
执行完一个yield 除非next才会执行下一个
function * gen(){
console.log(111);
yield '一只没有耳朵';//函数代码的分隔符
console.log(222);
yield '一只没有尾部';
console.log(333);
yield '真奇怪';
console.log(444);
}
let iterator = gen();
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
//遍历 与上等价
for(let v of gen()){
console.log(v);
}
生成器中有Symbol.iterator()所以可以用 for of
3.生成器函数参数
1.全局参数
2.iterator.next(参数)//参数是上一个返回参数
function * gen(arg){
// console.log(arg);
let one = yield 111;
console.log(one);//就是上一个 即111的返回参数 故打印BBB
let two = yield 222;
console.log(two);
let three = yield 333;
console.log(three);
}
//执行获取迭代器对象
let iterator = gen('AAA');
console.log(iterator.next());
//next方法可以传入实参
console.log(iterator.next('BBB'));
console.log(iterator.next('CCC'));
console.log(iterator.next('DDD'));
3.实例
异步编程 文件操作 网络操作(ajax, request) 数据库操作 1s 后控制台输出 111 2s后输出 222 3s后输出 333
回调地狱
得一层一层套下去 虽然简单 容易出错 如果有18层咋整?
setTimeout(() => {
console.log(111);
setTimeout(() => {
console.log(222);
setTimeout(() => {
console.log(333);
}, 3000);
}, 2000);
}, 1000);
生成器:
function one(){
setTimeout(()=>{
console.log(111);
iterator.next();
},1000)
}
function two(){
setTimeout(()=>{
console.log(222);
iterator.next();
},2000)
}
function three(){
setTimeout(()=>{
console.log(333);
iterator.next();
},3000)
}
function * gen(){
yield one();
yield two();
yield three();
}
//调用生成器函数
let iterator = gen();
iterator.next();
4.实例2
这里的getUsers()三个函数并没有iterator.next()方法 是因为把它们放在了构造器里面
//模拟获取 用户数据 订单数据 商品数据
function getUsers(){
setTimeout(()=>{
let data = '用户数据';
//调用 next 方法, 并且将数据传入
iterator.next(data);
}, 1000);
}
function getOrders(){
setTimeout(()=>{
let data = '订单数据';
iterator.next(data);
}, 1000)
}
function getGoods(){
setTimeout(()=>{
let data = '商品数据';
iterator.next(data);
}, 1000)
}
function * gen(){
let users = yield getUsers();
console.log(users);
let orders = yield getOrders();
console.log(orders)
let goods = yield getGoods();
console.log(goods)
}
//调用生成器函数
let iterator = gen();
iterator.next();
13.Promise
有俩参数,resolve(成功)、reject(失败) .then()中成功 会把p设为true并返回数据 失败会设为false 先简单这么理解吧 成功还是失败会直接影响then
1.基本语法
//实例化 Promise 对象
const p = new Promise(function(resolve, reject){
setTimeout(function(){
//
// let data = '数据库中的用户数据';
// resolve
// resolve(data);
let err = '数据读取失败';
reject(err);
}, 1000);
});
//调用 promise 对象的 then 方法
p.then(function(value){
console.log(value);
}, function(reason){
console.error(reason);
})
2.封装读取文件
1.调用方法读取文件
fs.readFile('./resources/为学.md', (err, data)=>{
//如果失败, 则抛出错误
if(err) throw err;
//如果没有出错, 则输出内容
console.log(data.toString());
});
2.用promise
const p = new Promise(function(resolve, reject){
fs.readFile("./resources/为学.md", (err, data)=>{
//判断如果失败
if(err) reject(err);
//如果成功
resolve(data);
});
});
p.then(function(value){
console.log(value.toString());
}, function(reason){
console.log("读取失败!!");
});
效果同上!
3.Promise封装AJAX请求
4.then方法
then方法的返回结果是 Promise 对象, 对象状态由回调函数的执行结果决定
如果回调函数中返回的结果是 非 promise 类型的属性, 状态为成功, 返回值为对象的成功的值
子promise返回成功 父promise同样返回成功 子失败 父同样失败 走到头再慢慢反
//创建 promise 对象
const p = new Promise((resolve, reject)=>{
setTimeout(()=>{
resolve('用户数据');
// reject('出错啦');
}, 1000)
});
//如果回调函数中返回的结果是 非 promise 类型的属性, 状态为成功, 返回值为对象的成功的值
const result = p.then(value => {
console.log(value);
//1. 非 promise 类型的属性
return 'iloveyou';
//2. 是 promise 对象
return new Promise((resolve, reject)=>{
// resolve('ok');
reject('error');
});
//3. 抛出错误
throw new Error('出错啦!');
throw '出错啦!';
}, reason=>{
console.warn(reason);
});
//链式调用
p.then(value=>{
}).then(value=>{
});
5.catch方法
类似于then
const p = new Promise((resolve, reject)=>{
setTimeout(()=>{
//设置 p 对象的状态为失败, 并设置失败的值
reject("出错啦!");
}, 1000)
});
p.then(function(value){}, function(reason){
console.error(reason);
});
p.catch(function(reason){
console.warn(reason);
});
效果一样的(颜色不一样哈)
6.Promise读取多个文件
//使用 promise 实现
const p = new Promise((resolve, reject) => {
fs.readFile("./resources/为学.md", (err, data) => {
resolve(data);
});
});
p.then(value => {
return new Promise((resolve, reject) => {
fs.readFile("./resources/插秧诗.md", (err, data) => {
resolve([value, data]);
});
});
}).then(value => {
return new Promise((resolve, reject) => {
fs.readFile("./resources/观书有感.md", (err, data) => {
//压入
value.push(data);
resolve(value);
});
})
}).then(value => {
console.log(value.join('\r\n'));
});
14.集合
集合是不重复的哈
//声明一个 set
let s = new Set();
let s2 = new Set(['大事儿','小事儿','好事儿','坏事儿','小事儿']);
//元素个数
console.log(s2.size);
//添加新的元素
s2.add('喜事儿');
//删除元素
s2.delete('坏事儿');
//检测
console.log(s2.has('糟心事'));
//清空
s2.clear();
console.log(s2);
for(let v of s2){
console.log(v);
}
例子
1.数组去重
let result = [...new Set(arr)];
console.log(result);
2. 交集
let arr2 = [4,5,6,5,6];
let result = [...new Set(arr)].filter(item => {
let s2 = new Set(arr2);// 4 5 6
if(s2.has(item)){
return true;
}else{
return false;
}
});
let result = [...new Set(arr)].filter(item => new Set(arr2).has(item));
console.log(result);
3.并集
let union = [...new Set([...arr, ...arr2])];
console.log(union);
4. 差集
let diff = [...new Set(arr)].filter(item => !(new Set(arr2).has(item)));
console.log(diff);