第三块 Vue的前置知识(中)

 

学习vue的前置知识


3. ES6

3.1 ES6简介

ECMA是“European Computer Manufacturers Association”的缩写,中文称欧洲计算机制造联合会。

这个组织的目标是评估,开发和认可电信和计算机标准。

ECMA是标准,JavaScript是实现

3.2 var与let&const

//之前var存在的问题
/*
	1.无块级作用域(可以用闭包解决)
	2.变量可以重复声明(主要也是由问题1导致)
	3.有变量提升
	4.无法限制修改
*/

let & var

{
	var a = 10;
}

consloe.log(a);//a = 10
{
	let a = 10;
}

consloe.log(a);//报错

const & var

本质是无法改变指向的内存地址,

const声明对象时,该对象不可以更换(栈 对象的地址不能更改),但是对象里的内容可以更改(堆 对象中的变量的地址它管不着,所以可以修改)

const person = {
    name:'张三',
    age:18
};
console.log(person);
// person = {} // 错误,无法更换对象
person.age = 19;
console.log(person);    // 发现不报错且age更改为19

3.3 箭头函数

//普通函数
const func1 =  function(x){
	return x;
}

//箭头函数(原版)
const func2 = (x) => {return x;}

//箭头函数精简版
const func3 = x => x;

精简规则

  • function换成=>放在参数和函数体中间
  • 如果没有参数,或有多个参数就需要使用()来定义参数列表
  • 如果有一个参数,可以不用()
  • 如果函数体中只有一条语句,可以不用,就不用使用return会自动加上

比较常见的使用

let arr = [4,5,67,8,9,08,7,6,5];
//普通函数
let narr1 = arr.sort(function(a,b){return a-b;}) 
//箭头函数
let narr2 = arr.sort((a,b)=>a-b);

需要注意的细节

1.箭头函数返回对象时要加上小括号

const func = id =>({id:id,name:lido});
console.log(func(10).name);

2.this指向问题

普通函数的this:指向它的调用者,如果没有调用者则默认指向window.

箭头函数的this:指向箭头函数定义时所处的对象,而不是箭头函数使用时所在的对象,默认使用父级的this.

综上:箭头函数没有自己的this,它的this是继承而来,默认指向在定义它时所处的对象(宿主对象).

大白话就是:普通函数this指自己,箭头函数this指父类

//1.箭头函数没有构造方法
function demo(){}//普通函数是有构造函数的
const obj = new demo();
console.log(obj);

const demo1 = () => {};
const obj2 = new demo1();
console.log(obj2);//报错

//2.this
const obj1 = {
    fun:function(){
        console.log(this);
    }
}; 
obj1.fun()//输出obj1

const obj2 = {
    fun:()=>{
        console.log(this);
    }
}; 
obj2.fun();//输出Window对象

function fun2(){
    console.log(this);
}
//没有对象的调用者
fun2();//输出Window对象

this的父级指向的体现

//以前的写法,需要拿到外面的父类
box.onclick = function(){
    const obj = this;
	setTimeout(function(){
		console.Log(obj);
		obj.className = 'xxx';
	},3000);
}

//箭头函数的this刚好就是可以直接拿到外面的父类
box.onclick = function(){
	setTimeout(=>(){
		console.Log(obj);
		obj.className = 'xxx';
	},3000);
}

3.4 数组中常见的高级方法

  1. filter() //自带循环,用于设定区间排除数
  2. map() //自带循环,用于操作数字
  3. reduce() //自带循环和上一次结果返回值,累计效果
  4. some() //数组中有一个为真就为真
  5. every() //数组中有一个为假就为假

前三个方法就是内置了循环,方便写业务逻辑

let myArray = [3,2,45,8,9,8,76,4,52,7,56,8,9,8,76,5,46,5,7,6,8,7];

//选出大于10的数字
let arr1 = myArray.filter(n => n>10);
console.log(arr1);

//再将选出的数字乘以0.7
let arr2 = arr1.map(n => n*0.7);

//再汇总
let sum1 = arr2.reduce((s,n) => s+n);//s是上一次的return的结果,所以有累加的效果
console.log(sum1);

//链式写法
let sum2 = myArray.filter(n => n>10).map(n => n*0.7).reduce((s,n) => s+n);
console.log(sum2);

3.5 map和set

set

添加啥都行,不能重复

const obj = new Set();
obj.add(1);
obj.add(2);
obj.has(1);
obj.delete(1);
obj.size();
obj.clear();

//循环遍历
obj.forEach(n => console.log(n))

map

重复会覆盖

键值遍历的方法都有

const obj = new Map();
obj.set('one',"lihua");
obj.set('two',123);
...

3.6 字符串新增的方法

startsWith();

endsWith();

    let urL = "https://www.baidu.com";
    if (urL.startsWith("https")) {
        console.log(urL);
    } else {
        console.log("不是以https开头的");
    }
    if (urL.endsWith('cn')) {
        console.log(urL);
    } else {
        console.log("不是以.cn结尾的URL ");
    }

template语法

let title ="Title";
let slogen ="balabala";

let jsx = `
		<hi>${title}/h1>
		<b>lido</b>
		<div><i>${slogen}</i></div>
	`;
console.log(jsx);

3.7 解构赋值

对于普通数组

看重顺序,不管名称

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, b, c] = arr;
}

对于对象

看重名称,不管顺序

let {anotherName, age, gender} = {name:'zhangsan', age:10, gender:'male'};
    console.log(anotherName, age, gender)// undefined 10, male
    

其他

1.普通值左边的值可以少于右边的值,会按顺序赋值

let arr = [1,2,3];
{
    let [a, b] = arr;
    console.log(a,b);   // 1 2
}
复制代码

2.对象左值也可以少于右边的,且顺序可以改变,因为对象按键名来赋值

let person = {
    name:'zhangsan',
    age:10,
    gender:'boy'
}
{
    let {gender, age} = person;
    console.log(gender, age)    // boy 10
}

3.复合赋值

let arr = [{name:'zhangsan', age:10}, [1,2,3], 'hello', 9 ];
{
    let [a,b,c,d] = arr;
    console.log(a);
    console.log(b,c,d);
}

4.分解赋值

let arr = [{name:'zhangsan', age:10}, [1,2,3], 'hello', 9 ];
{
    let[{name,age},[a,b,c],d,e] = arr;
    console.log(name,age);  // zhangsan 10
    console.log(a,b,c);     // 1 2 3 
    console.log(d,e);       // hello 9

}

5.声明与赋值不可分开

let [a,b];  // 报错 let [a,b] = arr;

3.8 拓展运算符

三点拓展运算符

拓展数组

let array1 = [1,2,3];
let array2 = [7,8,9];
let myArray = [...array1, 4, 5, 6, ...array2] ;
console.log(myArray)    // 1, 2, 3, 4, 5, 6, 7, 8, 9

拓展函数参数

function myFunction(a, b, c) {
    console.log(a,b,c);     
    return a+b+c;
}
let arr = [1,2,3];
console.log(myFunction(...arr));    

可变参数

function myFunction1(...args) {
    for(let i = 0; i <args.length; i++)
    {
        console.log(args[i]);
    }
    console.log(args);
}
myFunction1(3,12,45,123);

function myFunction2(a,b,...args) {
	console.log(a);//3
	console.log(b);//4
    for(let i = 0; i <args.length; i++)
    {
        console.log(args[i]);
    }
    console.log(args);//[45,123]
}
myFunction2(3,12,45,123);

3.9 对象

创建对象和使用

// 创建类
class Person {
    // 创建构造函数
    constructor(name, age, gender){
        this.name = name;
        this.age = age;
        this.gender = gender;
    }
    // 创建类中方法
    say() {
        console.log(this.name+' '+this.age+' '+this.gender);
    }
}

// 创建实例
let person1 = new Person('zhangsan', 18, 'male');
// 调用say()函数
person1.say();  // zhangsan 18 male

继承

<script>
    class Person {
        // 创建构造函数
        constructor(name, age, gender) {
            this.name = name;
            this.age = age;
            this.gender = gender;
        }
        // 创建类中方法
        say() {
            console.log(this.name + ' ' + this.age + ' ' + this.gender);
        }
    }

    class Students extends Person {
        constructor(name, age, gender, num) {
            super(name, age, gender)
            this.num = num;
        }

        say() {
            console.log(this.name, this.age, this.gender, this.num);
        }
    }

    student1 = new Students('lisi', 19, 'male', 23)
    student1.say(); // lisi 19 male 8003119
</script>

3.10 JSON

简写

name = 'zhangsan';
age = 15;
//{}json格式,当name:name相同时,可以简写为name
let obj = {
	name,
	age,
	say(){
		console.log(this.name, this.age)
	}
}

json串行化和反串行化

<script>
    name = 'zhangsan';
    age = 15;
    let obj = {
        name,
        age
    }
    let str = JSON.stringify(obj);
    console.log(str.name)   // undefined
    console.log(str)    // {"name":"zhangsan","age":15}

    let obj1 = JSON.parse(str)
    console.log(obj1.name, obj1.age)    // lisi 19
</script>

3.11 模块化编程

摘抄自博客

争对js文件中命名重复和打包的方便的解决办法

使用module来分隔

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="./1.js" type='module'></script>
    <script src="./2.js" type='module'></script>
    <script src="./3.js" type='module'></script> 
</head>
<body>
    
</body>
</html>

js导出

// 1.js

let name = 'zhangsan';
function add(a, b){return a+b}

export {name, add};  // 注意这里是json的简化写法,相当于 export {name:name};

js导入

// 3.js

import {name, add} from './1.js';   
// 注意这里使用了解构赋值,相当于:
// let {name, add} = {name:name, add:add} (这个对象来自./1.js文件的export)

// 接下来我们便可以直接使用name与add
console.log(name);  // zhangsan
console.log(add(3, 9)); // 12

解决命名冲突

当我们从其他文件引入变量后,也可能出现命名重复

// 3.js
import {name} from './1.js';
import {name} from './2.js';

这时候我们可以采用取别名的方法

// 3.js
import {name as name1} from './1.js';
import {name as name2} from './2.js';
// 接下来使用name1或者name2即可

同样的你也可以在1.js或者2.js暴露属性时取别名

// 1.js

let name = 'zhangsan';

export {name as name1};
复制代码
// 2.js

let name = 'lisi';

export {name as name2};
复制代码
// 3.js
import {name1} from './1.js';
import {name2} from './2.js';

console.log(name1, name2);  // zhangsan lisi

定义属性时暴露

我们可以在定义属性时就将他暴露出去

// 1.js
export let name = 'zhangsan';

这样暴露出去的属性在本文件中仍能使用

// 1.js
export let name = 'zhangsan';
console.log(name);  // zhangsan

缺少名字的暴露属性

函数或类等可以不用取名字就直接暴露

// 1.js
export default function(a){
    console.log(a)
}

接收时名字不需要{}

// 3.js
import printa from './1.js'
// 这里的printa是自己定义的

每个js文件只能定义这样的一个export default,

// 1.js
export default function(a){
    console.log(a)
}
export default function(a){
    return b;
}

接收暴露的所有属性

你可以将某个js文件暴露的属性全部导入,并将其放入一个对象中以便访问

export * as name from 'url';   // 创建一个对象接收暴露的所有属性

3.12 Promise异步计算

基础用法

// 分开写
<script>
    //resolve,reject是回调函数
    new Promise((resolve, reject) => {
        console.log("第一层");

        //正确的回调,相当于return
        resolve("第二层");
    }).then(res => {
        //接收
        console.log("res: " + res);
    })

    new Promise((resolve, reject) => {
        console.log("第一层");

        //错误的回调,相当于throw
        reject("第二层");
    }).catch(err => {
        //接收
        console.log("rej: " + err);
    })
</script>

//合着写
<script>
    //resolve,reject是回调函数
    new Promise((resolve, reject) => {
        console.log("第一层");

        //正确的回调,相当于return
        // resolve("第二层");
        reject("第二层");
    }).then(res => {
        //接收resolve(return)
        console.log("res: " + res);
    }, err => {
        //接收reject(throw)
        console.log("rej: " + err);
    })
</script>

嵌套

<script>
    new Promise((resolve, reject) => {
        console.log("第一层");
        resolve("第二层");
    //==============第一层====================
    }).then(res => {
        console.log("res_1: " + res);
        //嵌套
        return Promise.resolve("第三层");
        //如果是resolve,可以简写
        // return "第三层";
    }, err => {
        console.log("rej_1: " + err);
    //==============第二层====================
    }).then(res => {
        console.log("res_2: " + res);
    })
</script>

<script>
    function demo(mess, t) {
        return new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve(mess);
            }, t*1000);
        });
    }

    new Promise((resolve, reject) => {
        console.log("第一层");
        resolve("第二层");
        //==============第一层====================
    }).then(res => {
        console.log("res_1: " + res);
        return demo("第三层",2);
    }, err => {
        console.log("rej_1: " + err);
        //==============第二层====================
    }).then(res => {
        console.log("res_2: " + res);
        return demo("第四层",2);
    }).then(res => {
        console.log("res_3: " + res);  
    })
</script>

错误捕获

一次catch捕所以

<script>
    function demo(mess, t) {
        return new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve(mess);
            }, t*1000);
        });
    }

    new Promise((resolve, reject) => {
        console.log("第一层");
        resolve("第二层");
        //==============第一层====================
    }).then(res => {
        console.log("res_1: " + res);
        return demo("第三层",2);
    }, err => {
        console.log("rej_1: " + err);
        //==============第二层====================
    }).then(res => {
        console.log("res_2: " + res);
        return demo("第四层",2);
    }).then(res => {
        console.log("res_3: " + res);
        throw "error!";  
    }).catch(err=>{
        console.log("catch: " + err);  
    })
</script>

并发

<script>
    function demo(mess, t) {
        return new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve(mess);
            }, t * 1000);
        });
    }

    Promise.all([
        demo("第1", 1),
        demo("第2", 2),
    ]).then(res => {
        console.log(res[0]);
        console.log(res[1]);
    });
</script>