学习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 数组中常见的高级方法
- filter() //自带循环,用于设定区间排除数
- map() //自带循环,用于操作数字
- reduce() //自带循环和上一次结果返回值,累计效果
- some() //数组中有一个为真就为真
- 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>