Skip to main content

前言

【内容】

【目的】

【学习资源】


ES6

let声明变量

【格式】

let a;						//可声明单个变量
let b,c,d; //可声明多个变量
let e=100; //可声明同时为变量赋值
let f=521, g='lao',h=[]; //可赋值为数值、字符串、数组;

【特性】

  • 变量不能重复声明

    【报错示例】

    let a='lao';
    let a='jarvee';

    1653433243649

  • 块级作用域(全局,函数,eval)

    • 在代码块里有效,出代码块就无效了(相当于局部变量)
  • 不存在变量提升

    【报错示例】说明不能在变量声明之前,调用变量

    console.log(name);
    let name='Lao';

    1653433645346

  • 不影响作用域链

    【示例】说明在同一代码块中,下一级代码块任然可以调用let定义的变量

    {
    let name = 'lao';
    function fn(){
    console.log(name);
    }
    fn();
    }

const声明常量

【格式】

const 常量名=常量值

【特性】

  • 一定要有初始值

    【报错示例】

    const A;

    1653434898927

  • 一般声明使用大写(潜规则)

  • 常量值不能修改

    【报错示例】

    const NAME = 'Lao';
    NAME = 'Jarvee';

    1653435011876

  • 也是块级作用域内有效

    【报错示例】

    {
    const PLAYER = 'Lao';
    }
    console.log(PLAYER);

    1653435123943

  • 对于对数组和对象里元素修改,不算对常量进行修改 (因为地址没改变)

变量的解构赋值

  • 按照一定模式从数组和对象中提取值,对变量进行赋值

数组的解构

【示例】

const NUMBER = ['one','two','three'];
var [a,b,c] = NUMBER;
console.log(a); //输出one
console.log(b); //输出two
console.log(c); //输出three

对象的解构

【示例】

const Lao = {
name:'Jarvee',
age:'21',
doing:function(){
console.log("I am studying ES6");
}
};
let {name,age,word} = Lao;

console.log(name); //输出Jarvee
console.log(age); //输出21
console.log(doing()); //输出I am studying ES6

模板字符串

  • ES6引入新的声明字符串的方式反引号(``)

声明

【示例】

let str =`用反引号框起来的内容也是字符串`
console.log(str,typeof str); //输出 用反引号框起来的内容也是字符串 string

内容中可以直接出现换行符

【报错示例】使用" "|''都不能实现换行【解决办法】只能在每一个换行处加入+连接

 let str = '<ul>
<li>one</li>
<li>two</li>
<li>three</li>
</ul>';

1653446236447

【示例】使用反引号可以直接出现换行符

let str = `<ul>
<li>one</li>
<li>two</li>
<li>three</li>
</ul>`;

变量拼接

【格式】

let stringOne="String1";
let stringTwo=`${stringOne}this is String2`

对象的简化写法

  • 允许在大括号里面,直接写入变量和函数,作为对象的属性和方法

【示例】用ES6简化写法

let name='Lao'
let doing=function(){
cosole.log('Im coding!!!!');
}

//直接写入变量name
//直接写入函数doing
const Person={
name,
doing,
improve(){
console.log("Leaning ES6");
}
}

【对比上例】过去写法

let name='Lao'
let doing=function(){
cosole.log('Im coding!!!!');
}
const Person={
name:name,
doing:doing,
improve=function(){
console.log("Leaning ES6");
}
}

箭头函数以及声明特点

  • ES6允许使用箭头=>定义函数

声明一个函数

let fn=function(形参列表){
//函数体
}
//省略function关键字
let fn= (形参列表) =>{
//函数体
}

调用函数

let result=fn(形参列表)

箭头函数与普通函数的区别

【拓展】JavaScript this关键字

面向对象语言中this表示当前对象的一个引用

但在JavaScript中this不是固定不变的,它会随着执行环境的改变而改变。

执行环境this表示
在方法中该方法所属的对象
如果单独使用全局对象
在函数中全局对象
在函数中,在严格模式下未定义的(undefined
在事件中接收事件的元素
类似call()apply()方法可以将this引用到任何对象
  • this是静态的,this始终指向函数声明时所在作用域下的this的值

    【示例】说明箭头函数的this不可变

    //普通函数
    function getName(){
    console.log(this.name);
    }
    //箭头函数
    let getName2 = ()=>{
    console.log(this.name);
    }
    //设置window对象的name属性,是箭头函数声明所在作用域下的值
    window.name = 'lao';

    const person = {
    //这个name属性不在箭头函数所在作用域下
    name:'anthor Man'
    }
    //直接调用
    getName(); //lao
    getName2(); //lao
    //call方法调用
    getName.call(person); // anthor Man
    getName2.call(person); // lao
  • 不能作为构造实例化对象

    【报错示例】

    let Person = (name,age)=>{
    this.name=name;
    this.age=age;
    }
    let me = new Person('lao',21);
    console.log(me);

    1653464010380

  • 不能使用arguments变量

    【报错示例】

    let fn = () => {
    console.log(arguments);
    }
    fn(1,2,3);

    1653464113052

  • 箭头函数的简写

    • 省略小括号,当形参有且只有一个的时候

      【示例】

      let add = n =>{
      return n+n;
      }
      console.log(add(9));
    • 省略花括号,当代码体只有一条语句的时候,此时return必须省略

      • 而且语句的执行结果就是函数的返回值

      【示例】

      let pow (n)=>{
      return n*n;
      }
      console.log(pow(9));
      //用箭头函数简写
      let pow = n =>n*n;
      console.log(pow(9));

箭头函数的应用场景

适合不适合
与this无关的回调与this有关的回调
如定时器,数组的方法回调事件回调,对象的方法

函数参数的默认值设置

  • ES6允许函数参数赋初始值

形参初始值 具有默认值的参数,一般位置要靠后(潜规则)

【示例】

function add(a,b,c=3){
return a+b+c;
}
let result=add(1,2); //输出 6
console.log(result);

与解构赋值结合

【示例】

//可以给host属性赋初始值,如果对象中host属性没有传,默认为127.0.0.1
function connect({host="127.0.0.1", username,password, port}){
console.log(host)
console.log(username)
console.log(password)
console.log(port)
}
connect({
host: 'laojarvee.com',
username: 'root',
password: 'root',
port: 3306
})

rest 参数

  • ES6引入rest参数 用来获取函数的实参,代替arguments

【示例】ES5获取实参的方式

function date(){
console.log(arguments);
}
date('白天','中午','黑夜');
  • 【获得】一个对象

    1653466316963

【示例】ES6使用rest参数获取实参

function date(...args){
console.log(args);// filter some every map
}
date('早餐','午餐','晚餐');
  • 【获得】一个数组,可以对其使用数组的API方法如(filtersomeeverymap等方法)

    1653466609968

【==注意==】

  • 如果参数存在多个,rest参数必须放到参数最后

    【报错示例】**正确应该fn(a,b,...args)**

     function fn(a,...args,b){
    console.log(a);
    console.log(b);
    console.log(args);
    }
    fn(1,2,3,4,5,6);

    1653466923121

扩展运算符

  • ... 扩展运算符能将 数组转换为,分隔的参数序列

    【示例】

    //声明一个数组
    const food = ['早餐','午餐','晚餐'];
    //声明一个函数
    function eat(){
    console.log(arguments);
    }
    eat(food); //参数是一个数组
    eat(...food); //说明用扩展运算符可以将数组展开成一个参数序列

    1653469425092

拓展运算符应用

数组合并

【示例】

const workday=['星期一','星期二','星期三','星期四','星期五'];
const restday=['星期六','星期天'];

//ES5合并方法
const weekdayES5=workday.concat(restday);
//ES6合并方法
const weekdayES6=[...workday,...restday];
//输出都为['星期一','星期二','星期三','星期四','星期五','星期六','星期天']
console.log(weekdayES5);
console.log(weekdayES6);

数组克隆

【示例】浅拷贝

const name = ['L','A','O'];
const fastName = [...name];// ['L','A','O']
console.log(fastName);

将伪数组转为真正的数组

<body>
<div></div>
<div></div>
<div></div>
<script>
const divs = document.querySelectorAll('div');
console.log(divs); //显示的是一个对象伪数组
const divArr = [...divs]; //通过扩展运算符变成真数组
console.log(divArr);// arguments 也可以转
</script>
</body>

1653470927404

Symbol

  • ES6引入了一种新的原始数据类型Symbol,表示独一无二的值。
  • 它是Javascript语言的第七种数据类型,是一种类似与字符串的数据类型

【特点】

  • 值是唯一的,用来解决命名冲突问题

  • 值不能与其他数据进行运算

    【报错示例】

    let s=Symbol();
    let result=s+100; //说明Symbol不能进行四则运算
    let result=s>100; //说明Symbol不能进行比较
    let result=s+"string"; //说明Symbol不能进行字符串拼接
    let result=s+s;

    1653471965964

  • 定义的对象属性不能使用for...in循环遍历,但是可以使用Reflect.ownKeys来获取对象的所有键名。

创建Symbol对象

Symbol()创建一个函数

【示例】

let s= Symbol();

/*
通过描述字符串更好的知道这个值的作用,
与注释差不多,
表示出这个Symbol是干嘛的,为谁设置的
*/
let s2=Symbol('描述字符串');
let s3=Symbol('描述字符串');

/*
说明:描述字符只是标志,它所返回结果是不一样的,编号是不一样的
*/
console.log(s2===s3);//输出为false

【==注意==】描述字符串只是标志

Symbol.for()创建Symbol对象

【示例】

let s4=Symbol.for('Lao');
let s5=Symbol.for('Lao');

/*
说明:通过Symbol.for()创建,可以通过描述字符串得出一个唯一的Symbol值的
*/
console.log(s4===s5); //输出结果为true

【拓展】巧记JavaScript类型:USONB(you so NB)

u undefined

s string symbol

o object

n null number

b boolean

给对象添加Symbol类型的属性、方法方式

为什么要给对象添加Symbol类型的属性和方法

  • 很安全
    • 【解释】不会破坏原有的一些属性,可能对象里面原来就有该属性、方法,使用Symbol不会改变原有的属性和方法
  • 很快速

方式一

【示例】已有对象game,向该对象添加up,down方法

//已有对象game
let game={···

//声明对象
let methods ={
up:Symbol(),
down: Symbol()
};

game[methods.up]=function(){
console.log*("我可以改变形状");
}

game[methods.down]=function(){
console.log*("我可以快速下降!!!");
}

console.log(game);

方式二

【示例】

let youxi = {
name:"狼人杀",
[Symbol('say')]: function(){
console.log("我可以发言")
},
[Symbol('zibao')]: function(){
console.log('我可以自爆');
}
}

console.log(youxi)

【==注意==】要想给对象添加唯一的属性不能直接添加

  • 【错误示例】因为Symbol()是一个动态值是个表达式,不是一个静态的属性

    let youxi = {
    name:'狼人杀',
    Symbol():function(){

    }
    }

Symbol的内置属性

了解更多Symbol内置属性

迭代器

啥是迭代器?

  • 迭代器(Iterator)是一种接口,为各种不同的数据结构提供统一的访问机制。
  • 任何数据结构只要部署 Iterator 接口,就可以完成遍历操作。

啥是接口?

  • 其实就是对象里的一个属性

哪些数据结构原生具备iterator接口可用for...of遍历的数据?

  • Arrray

    【示例】

    const xiyou=['唐僧','孙悟空','猪八戒','沙僧'];
    for(let v of xiyou){
    console.log(v);
    }
    for(let v in xiyou){
    console.log(v);
    }

    【==注意==】for...infor...of的区别

    1653550192965

    for...infor...of
    前面变量保存键名键值
    • for in 可以遍历数组和对象,通常用来遍历对象
      • 遍历对象: key得到的是对象的每一个key
      • 遍历数组: key得到的是数组的下标
    • for of 遍历数组
      • 遍历数组: key得到的是数组的每一项
  • Argument

  • Set

  • Map

  • String

  • TypedArray

  • NodeList

上述数据结构中都有此接口,所以可以使用for...of来遍历

1653550553745

工作原理

  • 创建一个指针对象,指向当前数据结构的起始位置

    let iterator=xiyou[Symbol.iterator]();
  • 第一次调用对象的next()方法,指针自动指向数据结构的第一个成员

    console.log(iterator.next());

    1653551154445

  • 接下来不断调用next()方法,指针一直往后移动,直到指向最后一个成员

    console.log(iterator.next());
    console.log(iterator.next());
    console.log(iterator.next());
    console.log(iterator.next());

    1653551231604

  • 每调用next()方法放回一个包含valuedone属性的对象

【==注意==】需要自定义遍历数据的时候,要想到迭代器

如何自定义一个遍历?

【示例】

//声明一个对象
const avenger = {
name: "复仇者联盟",
members: [
'美国队长',
'钢铁侠',
'雷神',
'黑寡妇'
],
/*1、引入iterator接口*/
[Symbol.iterator]() {
//索引变量---控制向下的发展
let index = 0;
let _this = this;
/*2、设置返回值*/
return {
/*3、每次调用next方法*/
next: function () {
/*4、每调用next()方法放回一个包含value和done属性的对象*/
//要对返回结果进行一个处理
if (index < _this.members.length) {
const result = { value: _this.members[index], done: false };
//下标自增
index++;
//返回结果
return result;
}else{
return {value: undefined, done: true};
}
}
};
}
}

//遍历这个对象
for (let v of avenger) {
console.log(v);
}

生成器

啥是生成器?

  • 其实就是一个特殊的函数

能干啥?

  • 异步编程

    • 【拓展】ES6之前如何实现异步编程

      纯回调函数

      node fs ajax mongodb

怎么用?

【格式】function关键字和函数名中间加*

function * 函数名(){}

【示例】体会生成器的特殊性

function * gen(){
console.log("hello generator")
}
let iterator=gen();
console.log(iterator); //特殊性1:并没有直接输出
iterator.next(); //特殊性2:需要调用对象的next方法,才会执行

【示例】了解yield是生成器函数的分隔符

function * gen(){
yield '一只没有耳朵';
yield '一只没有尾部';
yield '真奇怪';
}
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)
//}

1653553622656

生成器函数如何进行参数传递?

【示例】

  • 说明:
    • 1、生成器整体函数可以传参
    • 2、next方法可以传入实参(==第n次调用next()方法,他将作为第n-1个(上一个)yield语句的返回结果==)
//说明1:生成器整体函数可以传参
function * gen(arg){
console.log(arg);
let one = yield 111;
console.log(one);
let two = yield 222;
console.log(two);
let three = yield 333;
console.log(three);
}

//执行获取迭代器对象
let iterator = gen('AAA');
console.log(iterator.next());
//说明2:next方法可以传入实参
console.log(iterator.next('BBB'));
console.log(iterator.next('CCC'));
console.log(iterator.next('DDD'));

1653554244858

生成器如何解决回调地狱?

什么是回调地狱?

【示例】1s 后控制台输出"111" 2s后输出 "222" 3s后输出 "333"

setTimeout(() => {
console.log(111);
setTimeout(() => {
console.log(222);
setTimeout(() => {
console.log(333);
}, 3000);
}, 2000);
}, 1000);

如果继续要求**ns后输出"nnn"**估计代码横向长度可以堪比香飘飘了——连起来可以绕地球好几圈。

【示例】用生成器处理如上问题

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();

如果继续要求**ns后输出"nnn"**只需创建函数即可。

【示例】用生成器进行异步编程(通过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(); //开始执行 yield getUsers();

【总结】什么情况下采用生成器?

  • 待处理的数据之间有关联度的,关联度关系类似多米诺骨牌的数据。

Promise

  • 是ES6引入的在 JavaScript 中进行异步编程的新解决方案
  • 语法上,Promise是一个构造函数
  • 用来封装异步操作并可以获取其成功或失败的结果

如何使用Promise?

【示例】

//实例化 Promise对象
//对象有三种状态:初始化,成功,失败
const p = new Promise(function(resolve,reject){
//定义一个异步状态
setTimeout(function(){
//
let data='数据库中的用户数据'
//只要调用resolve,对象状态为成功,就会调用promise对象的then方法的第一个回调函数
resolve(data);

let err ='数据读取失败';
//调用完reject函数后,promise对象p就会变为失败状态
//p为失败状态就会调用promise对象的then方法的第二个回调函数
reject(err);
},1000);
})
//调用promise对象的then 方法
//then方法调用两个参数,两个参数都是方法
p.then(function(value){
//若成功调第一个回调函数
//成功的形参通常叫value
console.log(value)
},function(reason){
//若失败调第二个回调函数
//失败的形参通常叫reason
console.error(reason);
})

结语