ES6及以上学习笔记

视频地址: link

1.letconst的使用及注意点

  • let/const定义的变量并没有挂载到window上,故而不能通过window点出来

1.0var存在的问题

  • var定义的变量就直接挂载到window上了
for (var i = 0; i < 10; i++) {
    
    //小括号里面的i是一个全局变量 通过var定义的变量只有函数内部的局部变量和全局变量之分,for循环if判断中定义的都是全局变量
  //js的执行逻辑
  //(1)在js主程序(单线程)上的同步任务形成了一个主任务执行栈
  //(2)主线程之外还存在一个任务队列,这个队列存在一些按时间顺序存放的事件,如鼠标点击、计时触发等,主线程中每出现一个异步任务,任务队列就会增加一个异步任务的事件
  //(3)一般执行栈中的同步任务执行完毕,系统就会读取任务队列,看看哪些事件是可以执行的,一旦可以执行将进入执行栈开始执行
  //(4)不断重复以上动作

  //如果真的用var,这里面就不能存在不进行特别处理的异步操作,因为for(这里面是直接在主任务执行栈上操作的){
    
    
  //这里面的异步操作不在主程序栈上执行操作,需要等到主程序都执行完再执行}

  (function (i) {
    
    //这样的特殊处理
    setTimeout(() => {
    
    
      console.log(i);
    }, 1000 * i);
  })(i);
};
console.log(i);//10由于定义的是全局变量,导致污染了全局变量

if (true) {
    
    
  var a = 12;//相当于定义了一个全局变量   
}
console.log(a)//12

1.1let的使用及注意点

  • 注意点汇总
{
    
    
  let 定义的变量只能在这个块级作用域中使用,外部是不能调用的
  let 定义的变量没有预解析, 不存在变量提升,在代码块中,只要let定义的变量,在之前调用,都是会报错的!先定义后使用!
    在同一个块级作用域中不能重复的定义变量
  for循环,小括号中的是父级作用域而花括号中的是子集作用域
}
let就是相当于之前的var只不过每一个let都有自己的块级作用域

1.1.1let定义的变量只能在这个块级作用域中使用,外部是不能调用的

for (let i = 0; i < 10; i++) {
    
    
  console.log(i)//正常打印
}
// console.log(i)//报错:找不到i

if (true) {
    
    
  let a = 6;//通过let定义的变量只能在当前的代码块中调用
  console.log(a)//6
}
console.log(a)//报错找不到a

1.1.2let定义的变量没有预解析,不存在变量提升,在代码块中,只要let定义的变量,在之前调用,都是会报错的!先定义后使用!

let a = 12;
    function func() {
    
    //只要在当前的块级作用域中通过let定义了变量,那么一定会使用这个变量
        console.log(a);//报错 原因没有预解析这么一说了
        let a = 2;
    }
func();

1.1.3let在同一个块级作用域中不能重复的定义变量

var a = 12;
var a = 5;
console.log(a)//5后面定义的a会覆盖前面定义的a

let a = 1; 
let a = 2;// 在同一个块级作用域中不能重复的定义变量
console.log(a)//报错 Uncaught SyntaxError: Identifier 'a' has already been declared//a已经声明了

1.1.4 for循环,小括号中的是父级作用域而花括号中的是子集作用域

for (let i = 0; i < 3; i++) {
    
    //小括号中的是父级作用域而花括号中是子集作用域
  // console.log(i)//0/1/2;
  let i = 'xbc';
  console.log(i)//没有报错并且输出xbc/xbc/xbc
}

{
    
    //父级作用域父级作用域是访问不到子集作用域中的变量的
  let a = 12;
  {
    
    //子集作用域
    let a = 5;
    console.log('子集作用域:', a)//5
  }
  console.log('父级作用域:', a)//12
}

1.3const的使用及注意点

  • 注意点汇总
{
    
    	
	const 定义的变量只能在这个块级作用域中使用,外部是不能调用的
	const定义的变量没有预解析,不存在变量提升,在代码块中,只要let定义的变量,在之前调用,都是会报错的!先定义后使用!
	在同一个块级作用域中不能重复的定义变量
	for循环,小括号中的是父级作用域而花括号中的是子集作用域
} 
每一个const都有自己的块级作用域

1.3.1const的特性和let是一样的不同的是const定义好了就不能改变了

const a = 16;
a = 18;
console.log(a)//报错:分配给常量变量

1.3.2const定义完变量必须有值,不能先声明后赋值

const a;
a = 16;
console.log(a)//报错:声明中缺少初始值设定

1.3.3通过const指定的只能是普通的,不能是引用机制的例如数组

const arr = ['apple', 'banana'];
arr.push('orange');//对象是引用机制,所以能修改缓存,要想实现彻底的常量可以用Object.freeze(对象)方法
console.log(arr);//["apple", "banana", "orange"]

const arr =Object.freeze(['apple,banana']);//冻住数组可以,但是也只能限制push/unshift/shift/pop等方法,如果数组里面放置的是对象,通过数组[index].key的方式修改,也是不行的
arr.push('orange');
console.log(arr)//报错Uncaught TypeError: Cannot add property 1, object is not extensible

2.解构赋值

2.1解构数组

2.1.1基本使用-左右两边的数据结构要一致
let [a, b, c] = [1, 2, 3];
console.log(a,b,c)//1 2 3

let [a, [b, c]] = [12, [5, 6]];
console.log(a, b, c);//12/5/6

let [a, ...b] = [1, 2, 3];
console.log(a,b)//1 (2) [2, 3]
2.1.2设置默认值
let [a, b, c='暂无数据'] = [1, 2];
console.log(a,b,c)//1,2,暂无数据
2.1.3应用
交换a,b的值
let a = 12;
let b = 18;
[b, a] = [a, b];
console.log(a,b)//18,12

2.2解构对象

2.2.1基本使用-左右两边的数据结构要一致

let {
    
     age, name, job } = {
    
     name: 'xbc', age: 26, job: 'web开发' };
console.log(age, name, job)//26 "xbc" "web开发"

2.2.2设置别名

let {
    
     name: name1, age: age2, job: job3 } = {
    
     name: 'xbc', age: 26, job: 'web开发' };
console.log(name1)//xbc
console.log(age2)//26
console.log(job3)//web开发

2.2.3设置默认值

let {
    
     age, name, job, skill = 'cook' } = {
    
     name: 'xbc', age: 26, job: 'web开发' };
console.log(age, name, job, skill)//26 "xbc" "web开发" "cook"

2.2.4解构函数的返回值也可以解构原型上的任意方法

function getPos() {
    
    
	return {
    
    
		left: 10,
		right: 20,
		bottom: 30,
        top: 40
		}
	}
let {
    
     left, right, top, bottom:b } = getPos();
console.log('left',left)//10
console.log('right',right)//20
console.log('top',top)//40
console.log('bottom',b )//30

2.2.5函数传参

function func({
    
     name, age, sex = '男' }) {
    
    
  console.log(name, 'name')//xbc 
  console.log(age, 'age')//26
  console.log(sex, 'sex')//男
}
func({
    
     age: 26, name: 'xbc' });//最少传一个空对象

function func({
    
     name = 'xbc', age = 26, sex = '男' } = {
    
    }) {
    
    
  console.log(name, 'name')//xbc
  console.log(age, 'age')//26
  console.log(sex, 'sex')//男
}
func();

3.字符串模板

  • 使用方式:${变量的名称}优点:可以随意的换行

3.1基本使用

let name = 'xbc';
let age = 26;
let str = `这个人是${
      
      name}年龄是${
      
      age}`;
console.log(str)//这个人是xbc年龄是26

let data = [
  {
    
     title: '新闻', read: 1000 },
  {
    
     title: '科技创新助力政府推动数字生活  数字中国建设峰会', read: 666 },
  {
    
     title: '新闻1', read: 888 },
  {
    
     title: '中国经济发展韧性十足', read: 1666 },
  {
    
     title: '中国外交部:加征关税解决不了任何问题', read: 1888 },
  {
    
     title: '看!你的户口、土地、收入将发生这些变化', read: 999 }
]
let ul = document.querySelector('.ul');
for (let i = 0; i < data.length; i++) {
    
    
  let li = document.createElement("li")
  li.innerHTML = `
            <span>${
      
      data[i].title}</span>
            <span>${
      
      data[i].read}</span>
            <a href="javascript:;">详情</a>
        `
  ul.appendChild(li)
}

3.2字符串新加的一些方法

3.2.1字符串查找片段str.includes

  • 使用方式['需要判断的字符串'].includes('判断是否包含的片段')
  • 返回值:布尔
let str = 'apple banbana pear';
let index = str.indexOf('banbana');//返回的是索引的位置
if (index !== -1) {
    
    
  console.log('字符串中存在查找的值')
} else {
    
    
  console.log('字符串中没有查找的值')
}

let bool = str.includes('pear');
console.log(bool)//字符串中包含不包含需要查找的片段找到返回true找不到返回false精确查找需用正则表达式

3.2.2字符串是不是以某一个字符或者字符片段开头

  • 使用方式['需要判断的字符串'].startsWith('判断是否是根据这个字符串开头的字符串')
  • 返回值:布尔
let str = 'https://www.baidu.com';
let bool = str.startsWith('http');
console.log(bool)//返回true或者false

3.2.3字符串是不是以某一个字符或者字符片段结尾

  • 使用方式['需要判断的字符串'].startsWith('判断是否是根据这个字符串结尾的字符串')
  • 返回值:布尔
let str = 'xbc.jpg';
let bool = str.endsWith('jpg');
console.log(bool)//返回true或者false

3.2.4重复字符串

  • 使用方式str.repeat('需要重复的次数Number类型')
  • 返回值:一个新的字符串
let str='牧马人';
let newStr=str.repeat(3);//括号里面规定重复多少次
console.log(newStr);//返回一个新的字符串

3.2.5字符串填充-前填充

  • ['参考字符串'].padStart('填充完毕之后的字符串的长度','需要填充的字符串要放在参考字符串的前面')
  • 返回值:一个新的字符串
let name = '三';
let surname = '张'
let newName = name.padStart(surname.length + name.length, surname);
console.log(newName)//张三

3.2.6字符串填充-后填充

  • ['参考字符串'].padStart('填充完毕之后的字符串的长度','需要填充的字符串要放在参考字符串的后面')
  • 返回值:一个新的字符串
let surname = '李';
let name='四'
let newName = surname.padEnd(surname.length+name.length,name);
console.log(newName)//李四

4.函数

4.1函数的默认参数

function func(a = '暂无数据。。。', b = '暂无数据。。。') {
    
    //函数的默认值 
  console.log(a, b)//欢迎 暂无数据。。。
}
func('欢迎');

function position({
    
     x = 0, y = 0 } = {
    
    }) {
    
    //利用解构赋值,给定默认值
  console.log(x, y)//10 20
}
position({
    
     x: 10, y: 20 });

4.2函数的参数声明问题

  • 在函数中函数的参数默认已经被定义了,不能在当前的块中继续使用let/count声明已经在小括号中声明的变量了,和for不一样,函数没有子集作用域一说。
function show(a = 20) {
    
    
  let a = 101;
  console.log(a);//报错,a已经被定义了。。。
};
show();

4.3箭头函数

4.3.1基本使用

function show(a, b) {
    
    
  return a + b;
}
console.log(show(12, 5));//17

// ()=>{
    
    
  //完整的箭头函数格式
// }

let show1 = (a, b) => {
    
    
  return a + b
}
console.log(show1(5, 6));//11

let show2 = (a, b) => a + b;//默认就是return
console.log(show2(10, 20));//30

4.3.2箭头函数中this的注意点:定义函数所在对象,不再是调用时所在的对象

  • 使用了箭头函数,当前的this指向当前的对象,this指向的是定义函数所在的对象,而不是运行函数所在的对象了!
let json = {
    
    
  id: 1,
  show: function () {
    
    //这的this就是指向调用者的了
    // setTimeout(function () {
    
    
    //   console.log(this);//{window: Window, self: Window, document: document, name: "", location: Location, …}
    // }, 1000);

    setTimeout(() => {
    
    //使用了箭头函数,当前的this指向当前的对象,this指向的是定义函数所在的对象,而不是运行函数所在的对象了,这里没有this,往上找
      console.log(this);//{id: 1, show: ƒ}
    }, 1000);
  },

  show1: () => {
    
    //这里没有this往上找
    setTimeout(() => {
    
    //使用了箭头函数,当前的this指向当前的对象,this指向的是定义函数所在的对象,而不是运行函数所在的对象了,这里没有this,往上找
      console.log(this);//{window: Window, self: Window, document: document, name: "", location: Location, …}
    }, 1000);
  }
};

json.show();//这里面就是json
json.show1();//由于定义show1的是箭头函数,里面的定时器也是箭头函数,所以,他们都没有自己的this,只能往上找,最终找到window,即使通过call/apply都不能更改this的指向了

4.3.3箭头函数中是没有argurments的用即可

let show = (...arr) => {
    
    
  // console.log(arguments);//没有arguement
  console.log(arr);//[10, 20, 30]
};
show(10, 20, 30);

4.3.4箭头函数中不能当成构造函数

function Person(){
    
    
  this.name='张三'
}
let p=new Person();
console.log(p);//Person {name: "张三"}

let show=()=>{
    
    
  this.name='李四'
}
let s=new show();
console.log(s);//show is not a constructor

5.扩展运算符

5.1扩展运算符之数组相关操作

5.1.1展开数组

let arr=['apple', 'banana', 'orange']
console.log(...arr)//apple banana orange

5.1.2复制数组

  • 复制数组不是复制引用
let arr = [1, 2, 3];
let newArr = [...arr];
newArr.push(4);
console.log(arr, newArr);//[1, 2, 3],[1, 2, 3, 4]

5.1.3函数传参

5.1.3.1函数传参
function show() {
    
    
  let arr=Array.prototype.slice.call(arguments);
  return arr.sort(function (a, b) {
    
    
      return b - a
  })
};
console.log(show(1, -2, 33, -4, 35, 86))//[86, 35, 33, 1, -2, -4]

//扩展运算符,reset剩余运算符
//...[1,2,3,4,5,6]==>1,2,3,4,5,6;展开
//...1,2,3,4,5,6==>[1,2,3,4,5,6];收起
function show(...arr) {
    
    //用在函数的形参上
  return arr.sort(function (a, b) {
    
    
      return b - a
  });
}
let arr = show(1, -2, 33, -4, 35, 86);
console.log(arr);//[86, 35, 33, 1, -2, -4]
5.1.3.2利用扩展运算符将函数的参数提前展开,便于函数调用
function func(a, b, c) {
    
    
	console.log(a, b, c)
}
func(...[1, 2, 6]);//用在函数的实参上
5.1.3.3剩余运算符必须放到最后,不能放别处
function func(a,...b) {
    
    
	console.log(a, b)//1,[2, 6]
}
func(...[1, 2, 6]);

5.2扩展运算符之对象相关操作

5.2.1基本使用

let {
    
     x, y, ...z } = {
    
     x: 1, y: 2, a: 10, b: 20 };
console.log(x,y,z)//1 2 {a: 10, b: 20}

let json = {
    
     name: '张三', age: 26, sex: '男' };
let newJson = {
    
     ...json };
newJson.skill = 'web开发'
console.log(newJson)//{name: "张三", age: 26, sex: "男", skill: "web开发"}
console.log(json)//{name: "张三", age: 26, sex: "男"}

6.数组循环

6.0数组的新增方法

6.0.1Array.form:将伪数组转成数组或者将str,json转成数组

function show() {
    
    
  return Array.from(arguments).sort(function (a, b) {
    
    
    return a - b
  })
}
console.log(show(1, -2, 33, -4, 35, 86));//[-4, -2, 1, 33, 35, 86]
let str = 'xbc';
let arr = Array.from(str)
console.log(arr)// ["x", "b", "c"]
let json = {
    
     0: 'xbc', 1: 24 };
json.length = 2;//没有length的需要添加一个length才能正常转化
let arr = Array.from(json)
console.log(arr)// ["xbc",24]

6.0.2Array.of:将一组值转换成数组

let arr = Array.of('apple', 'banbana', 'orange');//类似于函数传参
console.log(arr)// ["apple", "banbana", "orange"]

6.0.3Array.fill:填充数组

let arr = new Array(10);//设置数组的长度
arr.fill('默认值');//规定数组的填充内容
console.log(arr)//["默认值", "默认值", "默认值", "默认值", "默认值", "默认值", "默认值", "默认值", "默认值", "默认值"]

6.0.4Array.includes:查找数组中是否包含某个字符片段

let arr = ['apple', 'banana', 'orange'];
let index = arr.indexOf('banana');
let bool = arr.includes('banana');//数组中是否包含需要查找的字符串
console.log(index)//1
console.log(bool)//true

6.1for of循环

6.1.1for of循环index

let arr = [
  {
    
     name: '张三', num: 181, bool: false },
  {
    
     name: '张三', num: 182, bool: false },
  {
    
     name: '张三', num: 183, bool: false },
  {
    
     name: '张三', num: 186, bool: false },
  {
    
     name: '张三', num: 185, bool: false },
  {
    
     name: '张三', num: 186, bool: false },
  {
    
     name: '张三', num: 187, bool: false },
  {
    
     name: '张三', num: 188, bool: false },
  {
    
     name: '张三', num: 189, bool: false },
  {
    
     name: '张三', num: 190, bool: false }
]

for (const index of arr.keys()) {
    
    
  console.log(index);//0 1 2 3 4 5 6 7 8 9
}

6.1.2for of循环item

let arr = [
  {
    
     name: '张三', num: 181, bool: false },
  {
    
     name: '张三', num: 182, bool: false },
  {
    
     name: '张三', num: 183, bool: false },
  {
    
     name: '张三', num: 186, bool: false },
  {
    
     name: '张三', num: 185, bool: false },
  {
    
     name: '张三', num: 186, bool: false },
  {
    
     name: '张三', num: 187, bool: false },
  {
    
     name: '张三', num: 188, bool: false },
  {
    
     name: '张三', num: 189, bool: false },
  {
    
     name: '张三', num: 190, bool: false }
]

for (const item of arr.values()) {
    
    
  console.log(item);
  //{name: "张三", num: 181, bool: false}
  //{name: "张三", num: 182, bool: false}
  //{name: "张三", num: 183, bool: false}
  //{name: "张三", num: 186, bool: false}
  //{name: "张三", num: 185, bool: false}
  //{name: "张三", num: 186, bool: false}
  //{name: "张三", num: 187, bool: false}
  //{name: "张三", num: 188, bool: false}
  //{name: "张三", num: 189, bool: false}
  //{name: "张三", num: 190, bool: false}
}

6.1.3for of循环key/item

let arr = [
  {
    
     name: '张三', num: 181, bool: false },
  {
    
     name: '张三', num: 182, bool: false },
  {
    
     name: '张三', num: 183, bool: false },
  {
    
     name: '张三', num: 186, bool: false },
  {
    
     name: '张三', num: 185, bool: false },
  {
    
     name: '张三', num: 186, bool: false },
  {
    
     name: '张三', num: 187, bool: false },
  {
    
     name: '张三', num: 188, bool: false },
  {
    
     name: '张三', num: 189, bool: false },
  {
    
     name: '张三', num: 190, bool: false }
]

for (const [key,item] of arr.entries()) {
    
    
  console.log(key,item);
  //0 {name: "张三", num: 181, bool: false}
  //1 {name: "张三", num: 182, bool: false}
  //2 {name: "张三", num: 183, bool: false}
  //3 {name: "张三", num: 186, bool: false}
  //4 {name: "张三", num: 185, bool: false}
  //5 {name: "张三", num: 186, bool: false}
  //6 {name: "张三", num: 187, bool: false}
  //7 {name: "张三", num: 188, bool: false}
  //8 {name: "张三", num: 189, bool: false}
  //9 {name: "张三", num: 190, bool: false}
}

6.2forEach

  • forEach方法里操作对象生效,想要操作里面的基本数据类型,就用arr[i]的形式直接操作数组。
  • arr.forEach/arr.map/arr.filter/arr.some/arr.every都能接受两个参数其一是回调函数其二是this(希望this指向谁)
  • 注意点:要想改变this的指向,回调函数必须是非箭头函数形式

6.2.1基本使用

let arr = [
  {
    
     name: '张三', num: 181, bool: false },
  {
    
     name: '张三', num: 182, bool: false },
  {
    
     name: '张三', num: 183, bool: false },
  {
    
     name: '张三', num: 186, bool: false },
  {
    
     name: '张三', num: 185, bool: false },
  {
    
     name: '张三', num: 186, bool: false },
  {
    
     name: '张三', num: 187, bool: false },
  {
    
     name: '张三', num: 188, bool: false },
  {
    
     name: '张三', num: 189, bool: false },
  {
    
     name: '张三', num: 190, bool: false }
]

arr.forEach(function (item, index) {
    
    //非箭头函数可以修改this指向
  console.log(item, index, this);
  //{name: "张三", num: 181, bool: false} 0 Number {996}
  //{name: "张三", num: 182, bool: false} 0 Number {996}
  //{name: "张三", num: 183, bool: false} 0 Number {996}
  //{name: "张三", num: 186, bool: false} 0 Number {996}
  //{name: "张三", num: 186, bool: false} 0 Number {996}
  //{name: "张三", num: 187, bool: false} 0 Number {996}
  //{name: "张三", num: 188, bool: false} 0 Number {996}
  //{name: "张三", num: 189, bool: false} 0 Number {996}
  //{name: "张三", num: 190, bool: false} 0 Number {996}
}, 996)

let arr = [
  {
    
     name: '张三', num: 181, bool: false },
  {
    
     name: '张三', num: 182, bool: false },
  {
    
     name: '张三', num: 183, bool: false },
  {
    
     name: '张三', num: 186, bool: false },
  {
    
     name: '张三', num: 185, bool: false },
  {
    
     name: '张三', num: 186, bool: false },
  {
    
     name: '张三', num: 187, bool: false },
  {
    
     name: '张三', num: 188, bool: false },
  {
    
     name: '张三', num: 189, bool: false },
  {
    
     name: '张三', num: 190, bool: false }
]

arr.forEach((item, index) => {
    
    //箭头函数无法修改this指向,因为箭头函数没有this,因为函数是在window中定义的,所以 this就是window
  console.log(item, index, this);
  //{name: "张三", num: 181, bool: false} 0 window
  //{name: "张三", num: 182, bool: false} 0 window
  //{name: "张三", num: 183, bool: false} 0 window
  //{name: "张三", num: 186, bool: false} 0 window
  //{name: "张三", num: 186, bool: false} 0 window
  //{name: "张三", num: 187, bool: false} 0 window
  //{name: "张三", num: 188, bool: false} 0 window
  //{name: "张三", num: 189, bool: false} 0 window
  //{name: "张三", num: 190, bool: false} 0 window
}, 996)

6.2.2修改item

let arr = [
  {
    
     name: '张三', num: 181, bool: false },
  {
    
     name: '张三', num: 182, bool: false },
  {
    
     name: '张三', num: 183, bool: false },
  {
    
     name: '张三', num: 186, bool: false },
  {
    
     name: '张三', num: 185, bool: false },
  {
    
     name: '张三', num: 186, bool: false },
  {
    
     name: '张三', num: 187, bool: false },
  {
    
     name: '张三', num: 188, bool: false },
  {
    
     name: '张三', num: 189, bool: false },
  {
    
     name: '张三', num: 190, bool: false }
]

arr.forEach((item, index) => {
    
    
  arr[index].addKey1 = item.name + item.num;
  arr[index].addKey2 = 'addKey2';
});
console.log(arr);
//[{name: "张三", num: 181, bool: false, addKey1: "张三181", addKey2: "addKey2"}
//{name: "张三", num: 182, bool: false, addKey1: "张三182", addKey2: "addKey2"}
//{name: "张三", num: 183, bool: false, addKey1: "张三183", addKey2: "addKey2"}
//{name: "张三", num: 186, bool: false, addKey1: "张三186", addKey2: "addKey2"}
//{name: "张三", num: 185, bool: false, addKey1: "张三185", addKey2: "addKey2"}
//{name: "张三", num: 186, bool: false, addKey1: "张三186", addKey2: "addKey2"}
//{name: "张三", num: 187, bool: false, addKey1: "张三187", addKey2: "addKey2"}
//{name: "张三", num: 188, bool: false, addKey1: "张三188", addKey2: "addKey2"}
//{name: "张三", num: 189, bool: false, addKey1: "张三189", addKey2: "addKey2"}
//{name: "张三", num: 190, bool: false, addKey1: "张三190", addKey2: "addKey2"}]

6.3map

6.3.1使用方法一

let arr = [
  {
    
     name: '张三', num: 181, bool: false },
  {
    
     name: '张三', num: 182, bool: false },
  {
    
     name: '张三', num: 183, bool: false },
  {
    
     name: '张三', num: 186, bool: false },
  {
    
     name: '张三', num: 185, bool: false },
  {
    
     name: '张三', num: 186, bool: false },
  {
    
     name: '张三', num: 187, bool: false },
  {
    
     name: '张三', num: 188, bool: false },
  {
    
     name: '张三', num: 189, bool: false },
  {
    
     name: '张三', num: 190, bool: false }
]

let newArr = arr.map((item, index) => {
    
    
  return {
    
    
    name1: item.name,
    height: item.num + 'cm'
  }
});
console.log(newArr);
//[{name1: "张三", height: "181cm"}
//{name1: "张三", height: "182cm"}
//{name1: "张三", height: "183cm"}
//{name1: "张三", height: "186cm"}
//{name1: "张三", height: "185cm"}
//{name1: "张三", height: "186cm"}
//{name1: "张三", height: "187cm"}
//{name1: "张三", height: "188cm"}
//{name1: "张三", height: "189cm"}
//{name1: "张三", height: "190cm"}]

6.3.2使用方法二

let arr = [
  {
    
     name: '张三', num: 181, bool: false },
  {
    
     name: '张三', num: 182, bool: false },
  {
    
     name: '张三', num: 183, bool: false },
  {
    
     name: '张三', num: 186, bool: false },
  {
    
     name: '张三', num: 185, bool: false },
  {
    
     name: '张三', num: 186, bool: false },
  {
    
     name: '张三', num: 187, bool: false },
  {
    
     name: '张三', num: 188, bool: false },
  {
    
     name: '张三', num: 189, bool: false },
  {
    
     name: '张三', num: 190, bool: false }
]

let newArr = arr.map((item, index) => {
    
    
  item.key1 = 'key' + index;
  item.key2 = 'key' + item.num;
  return item;
});
console.log(newArr);
//[{name: "张三", num: 181, bool: false, key1: "key0", key2: "key181"}
//{name: "张三", num: 182, bool: false, key1: "key1", key2: "key182"}
//{name: "张三", num: 183, bool: false, key1: "key2", key2: "key183"}
//{name: "张三", num: 186, bool: false, key1: "key3", key2: "key186"}
//{name: "张三", num: 185, bool: false, key1: "key4", key2: "key185"}
//{name: "张三", num: 186, bool: false, key1: "key5", key2: "key186"}
//{name: "张三", num: 187, bool: false, key1: "key6", key2: "key187"}
//{name: "张三", num: 188, bool: false, key1: "key7", key2: "key188"}
//{name: "张三", num: 189, bool: false, key1: "key8", key2: "key189"}
//{name: "张三", num: 190, bool: false, key1: "key9", key2: "key190"}]

6.4filter

  • 将符合条件的元素过滤出来返回一个新的数组如果回调函数返回是true就留下来
let arr = [
  {
    
     name: '张三', num: 181, bool: false },
  {
    
     name: '张三', num: 182, bool: false },
  {
    
     name: '张三', num: 183, bool: false },
  {
    
     name: '张三', num: 186, bool: false },
  {
    
     name: '张三', num: 185, bool: false },
  {
    
     name: '张三', num: 186, bool: false },
  {
    
     name: '张三', num: 187, bool: false },
  {
    
     name: '张三', num: 188, bool: false },
  {
    
     name: '张三', num: 189, bool: false },
  {
    
     name: '张三', num: 190, bool: false }
]

let newArr = arr.filter((item, index) => {
    
    
  return item.num > 185
});
console.log(newArr);
//[{name: "张三", num: 186, bool: false}
//{name: "张三", num: 186, bool: false}
//{name: "张三", num: 187, bool: false}
//{name: "张三", num: 188, bool: false}
//{name: "张三", num: 189, bool: false}
//{name: "张三", num: 190, bool: false}]

6.5some

  • 类似于查找,数组中的某一个元素符合条件就返回true
let arr = [
  {
    
     name: '张三', num: 181, bool: false },
  {
    
     name: '张三', num: 182, bool: false },
  {
    
     name: '张三', num: 183, bool: false },
  {
    
     name: '张三', num: 186, bool: false },
  {
    
     name: '张三', num: 185, bool: false },
  {
    
     name: '张三', num: 186, bool: false },
  {
    
     name: '张三', num: 187, bool: false },
  {
    
     name: '张三', num: 188, bool: false },
  {
    
     name: '张三', num: 189, bool: false },
  {
    
     name: '张三', num: 190, bool: false }
]

let bool = arr.some((item, index) => {
    
    
  return item.num > 185
});
console.log(bool);//true

6.6every

  • 数组中的所有元素都必须符合条件才返回true
let arr = [
  {
    
     name: '张三', num: 181, bool: false },
  {
    
     name: '张三', num: 182, bool: false },
  {
    
     name: '张三', num: 183, bool: false },
  {
    
     name: '张三', num: 186, bool: false },
  {
    
     name: '张三', num: 185, bool: false },
  {
    
     name: '张三', num: 186, bool: false },
  {
    
     name: '张三', num: 187, bool: false },
  {
    
     name: '张三', num: 188, bool: false },
  {
    
     name: '张三', num: 189, bool: false },
  {
    
     name: '张三', num: 190, bool: false }
]

let bool = arr.every((item, index) => {
    
    
  return item.num > 185
});
console.log(bool);//false

6.7reduce

let arr = [
  {
    
     name: '张三', num: 181, bool: false },
  {
    
     name: '张三', num: 182, bool: false },
  {
    
     name: '张三', num: 183, bool: false },
  {
    
     name: '张三', num: 186, bool: false },
  {
    
     name: '张三', num: 185, bool: false },
  {
    
     name: '张三', num: 186, bool: false },
  {
    
     name: '张三', num: 187, bool: false },
  {
    
     name: '张三', num: 188, bool: false },
  {
    
     name: '张三', num: 189, bool: false },
  {
    
     name: '张三', num: 190, bool: false }
]

let count = arr.reduce((prev, curr) => {
    
    
  console.log(curr);//{ name: '张三', num: 181, bool: false }开始
  return prev + curr.num
}, 0);
console.log(count);//1857

6.8reduceRight

let arr = [
  {
    
     name: '张三', num: 181, bool: false },
  {
    
     name: '张三', num: 182, bool: false },
  {
    
     name: '张三', num: 183, bool: false },
  {
    
     name: '张三', num: 186, bool: false },
  {
    
     name: '张三', num: 185, bool: false },
  {
    
     name: '张三', num: 186, bool: false },
  {
    
     name: '张三', num: 187, bool: false },
  {
    
     name: '张三', num: 188, bool: false },
  {
    
     name: '张三', num: 189, bool: false },
  {
    
     name: '张三', num: 190, bool: false }
]

let count = arr.reduceRight((prev, curr) => {
    
    
  console.log(curr);//{ name: '张三', num: 190, bool: false }开始
  return prev + curr.num
}, 0);
console.log(count);//1857

6.9find

  • 查找数组中符合条件的第一个元素并返回
let arr = [
  {
    
     name: '张三', num: 181, bool: false },
  {
    
     name: '张三', num: 182, bool: false },
  {
    
     name: '张三', num: 183, bool: false },
  {
    
     name: '张三', num: 186, bool: false },
  {
    
     name: '张三', num: 185, bool: false },
  {
    
     name: '张三', num: 186, bool: false },
  {
    
     name: '张三', num: 187, bool: false },
  {
    
     name: '张三', num: 188, bool: false },
  {
    
     name: '张三', num: 189, bool: false },
  {
    
     name: '张三', num: 190, bool: false }
]

let findObj= arr.find((item, index) => {
    
    
  return item.num > 185;
});
console.log(findObj);//{name: "张三", num: 186, bool: false}

6.10findIndex

  • 查找数组中符合条件的第一个元素并返回其对应的索引值
let arr = [
  {
    
     name: '张三', num: 181, bool: false },
  {
    
     name: '张三', num: 182, bool: false },
  {
    
     name: '张三', num: 183, bool: false },
  {
    
     name: '张三', num: 186, bool: false },
  {
    
     name: '张三', num: 185, bool: false },
  {
    
     name: '张三', num: 186, bool: false },
  {
    
     name: '张三', num: 187, bool: false },
  {
    
     name: '张三', num: 188, bool: false },
  {
    
     name: '张三', num: 189, bool: false },
  {
    
     name: '张三', num: 190, bool: false }
]

let index = arr.findIndex((item, index) => {
    
    
  return item.num > 185;
});
console.log(index);//3

7.对象

7.1对象的简洁语法

let name = '张三';
let age = 18;
let json = {
    
    
  name,//name:name
  age,//age:age
  skill: function () {
    
    
    console.log(this);//{name: "张三", age: 18, skill: ƒ}
  },
  skill1: () => {
    
    
    console.log(this);//window
  },
  skill2() {
    
    //{name: "张三", age: 18, skill: ƒ, skill1: ƒ, skill2: ƒ}
    console.log(this);
  }
};

json.skill();
json.skill1();
json.skill2();

7.2for of循环对象

7.2.1for of循环key

let json = {
    
    
  name: '张三',
  age: 16,
  sex: '男'
}

for (const key of Object.keys(json)) {
    
    
  console.log(key);// name age sex
}

7.2.2for of循环item

let json = {
    
    
  name: '张三',
  age: 16,
  sex: '男'
}

for (const item of Object.values(json)) {
    
    
  console.log(item);// 张三 16 男
}

7.2.3for of循环key item

let json = {
    
    
  name: '张三',
  age: 16,
  sex: '男'
}

for (const [key, value] of Object.entries(json)) {
    
    
  console.log(key, value);// name 张三  age 16  sex 男
}

7.3对象的简洁语法传参

let x = 10;
let y = 20;
function sum({
    
     x, y }) {
    
    
  return x + y
};

console.log(sum({
    
     x, y }))//30

7.4Object.is判断两个一模一样的东西是不是相等的

let bool = Object.is('a', 'a');
console.log(bool)//true判断两个一模一样的东西是不是相等 
let bool1 = Object.is(+0, -0);
console.log(bool1)//false判断两个一模一样的东西是不是相等 
let bool2 = Object.is(NaN, NaN);
console.log(bool2)//true判断两个一模一样的东西是不是相等 

7.5Object.assign(目标对象,对象1,对象2……)用途:复制对象,合并参数

let peopleInformation = {
    
    
  name: '张三',
  age: 24,
  sex: '男'
};
let skills = {
    
    
  skill1: 'web开发',
  skill2: 'cooking'
}
Object.assign(peopleInformation, skills);
console.log(peopleInformation)//name: "张三", age: 24, sex: "男", skill1: "web开发", skill2: "cooking"}

let defaultInformation = {
    
    
  name: '用户',
  age: 18,
  sex: '男'
}
let userInformation = {
    
    
  name: '张三',
  age: 26
};
let json = {
    
    }
Object.assign(json, defaultInformation, userInformation);
console.log(json)//{name: "张三", age: 26, sex: "男"}

8.Promise

  • 作用:解决异步回调问题
//传统方式,大部分用回调函数,事件
ajax(url,{//获取token
	ajax(url,()=>{//获取用户信息
		ajax(url,()=>{
			//获取用户相关的新闻
		})
	})
});

8.1promise语法

8.1.1基础语法

new Promise(function(resolve,reject){
    
    //返回一个promis对象
        //resolve:成功时候调用
        //reject:失败的时候调用
    });

8.1.2例一

let a = 10;
let json = new Promise(function (resolve, reject) {
    
    
  if (a == 10) {
    
    
    resolve('success')
  } else {
    
    
    reject('error')
  }
});

json.then(res => {
    
    
  console.log(res);//如果是a=10返回成功的结果
}, err => {
    
    
  console.log(err)//如果是a!=10返回的是失败的结果
})

8.1.2例二

let name = '张三'
let promiseObject = new Promise(function (resolve, reject) {
    
    
  if (name == '张三') {
    
    
    resolve('张三')
  } else {
    
    
    reject('其他人')
  }
});
promiseObject.then(success => {
    
    //then的返回值还是promise对象
  console.log(success)
}).catch(error => {
    
    //这个就等同于成功和失败都写在.then中的错误返回的函数
  console.log(error)
})

8.1.3综合实例

let status = 1;
let userLogin = (resolve, reject) => {
    
    
  setTimeout(() => {
    
    
    if (status == 1) {
    
    
      resolve({
    
     data: '登录成功', msg: 'xxx', token: 'asldkfjlskdfjlk' })
    } else {
    
    
      reject('登录失败')
    }
  }, 1000);
}

let userMsg = (resolve, reject) => {
    
    
  setTimeout(() => {
    
    
    if (status == 1) {
    
    
      resolve({
    
     data: '获取用户信息成功', msg: 'xxx', token: 'asldkfjlskdfjlk' })
    } else {
    
    
      reject('登录失败')
    }
  }, 1000);
}

new Promise(userLogin).then(res => {
    
    
  console.log(res);
  return new Promise(userMsg)
}).then(res => {
    
    
  console.log(res);
})

8.2Promise.resolve(‘需要处理的元素’)//将括号内的元素处理成一个resolve状态的promise对象(成功状态)

Promise.resolve('aaa').then(res => {
    
    
  console.log(res)//aaa
});

new Promise(function (resolve) {
    
    //这个等价于上面那个写的方式
  resolve('aaa')
}).then(res => {
    
    
  console.log(res)//aaa
});

8.3Promise.reject(‘需要处理的元素’)//将括号内的元素处理成一个reject状态的promise对象(失败状态)

Promise.reject('bbb').catch(err => {
    
    
  console.log(err)//bbb
})

new Promise(function (reject) {
    
    //这个等价于上面那个写的方式
  reject('bbb')
}).catch(res => {
    
    
  console.log(res)//bbb
});

8.4Promise.all([‘reslove对象1’,‘reslove对象2’, ‘reslove对象3’])

let a = Promise.resolve('aaa');
let b = Promise.resolve('bbb');
let c = Promise.resolve('ccc');
Promise.all([a, b, c]).then(arr => {
    
    //必须确保所有的promise都是resolve状态
  console.log(arr)//["aaa", "bbb", "ccc"]
  let [res1, res2, res3] = arr;
  console.log(res1, res2, res3)//aaa bbb ccc
});

8.5Promise. race([‘reslove对象1’,‘reslove对象2’, ‘reslove对象3’])

let a = Promise.resolve('aaa');
let b = Promise.resolve('bbb');
let c = Promise.reject('ccc');
Promise.race([a, b, c]).then(arr => {
    
    //只要有一个成功就返回
  console.log(arr)//aaa
});

9.模块化

  • 注意点:export import 都需要放到服务器的环境中
  • 如何定义模块?export
  • 如何使用模块? import

9.1import特点

9.1.1通过import引入的js模块即可以是相对路径也可以是绝对路径

9.1.1.1import引入绝对路径
import 'https://cdn.bootcdn.net/ajax/libs/jquery/1.8.3/jquery.js';
9.1.1.2import引入相对路径
import '../../module/index.js'//相对路径这么做相当于引入了一个js文件

9.1.2import无论导入多少次,只会导入一次

import '../js/func.js';
import '../js/func.js';
import '../js/func.js';
import '../js/func.js';
import '../js/func.js';
import '../js/func.js';

9.1.3导出去的模块,如果里面有内容更改,引入的时候也会更改,即使用定时器

let name = '张三';
export const age = 26;
setTimeout(() => {
    
    
  name='李四'
}, 2000);
export {
    
    
  name
}

import {
    
    name}  from '../js/func.js';
setTimeout(() => {
    
    
  console.log(name);
}, 2000);

9.1.4import有提升效果

new mod.People().showName('工作');
show();
sum();
console.log(a);
console.log(b);
import mod,{
    
    show,sum,a,b} from '../../model/index.js'

9.1.5import类似于node里面的require,可以动态引入,默认import语法不能写到if或者for中。

if(true){
    
    
  import ('https://cdn.bootcdn.net/ajax/libs/jquery/1.8.3/jquery.js').then(res=>{
    
    
    console.log($);
  })
}

let js='index-1.js'
if(js=='index-1.js'){
    
    
    import('../../model/index-1.js').then(res=>{
    
    
        console.log(res)
    })
}else{
    
    
    import('../../model/index-2.js').then(res=>{
    
    
        console.log(res)
    })
}

9.1.6按需加载 可以写在if中 路径 import的返回值是要给promise对象,可以用then

Promise.all([
    import('../../model/index-1.js'),
    import('../../model/index-2.js')
]).then(([index1,index2])=>{
    
    
    console.log(index1,index2)
})

9.2async await

async function main(){
    
    
    const mod1=await import('../../model/index-1.js');
    const mod2=await import('../../model/index-2.js');
    console.log(mod1,mod2);
    const [m1,m2]= await Promise.all([
        import('../../model/index-1.js'),
        import('../../model/index-2.js')
    ]);
    console.log(m1,m2);
}
main();

9.3设置别名

9.3.1在需要导出js文件中设置别名

9.3.1.1导出js文件
const userName = '肖宝成';
let age = 24;
const sex = '男'
function func(){
    
    
    console.log('func')
}
 export {
    
    
    userName as aaa,
    age as bbb,
    func as ccc,
    sex as ddd
}
9.3.1.2引入js文件
import {
    
     aaa,bbb,ccc,ddd } from '../../model/index-1.js'//相对路径
console.log(aaa);//肖宝成
console.log(bbb);//24
ccc();//func
console.log(ddd)//男

9.3.2在需要引入的js文件中设置别名

9.3.2.1导出js文件
const userName = '肖宝成';
let age = 24;
const sex = '男'
function func(){
    
    
    console.log('func')
}
 export {
    
    
    userName,
    age,
    func,
    sex
}
9.3.2.2引入js文件
import {
    
     userName as aaa,age as bbb,func as ccc,sex as ddd } from
'../../model/index-1.js'//相对路径
console.log(aaa);//肖宝成
console.log(bbb);//24
ccc();//func
console.log(ddd)//男

import * as modelName from '../../model/index-1.js'//相对路径
console.log(modelName)
//age: 24
//func: ƒ func()
//sex: "男"
//userName: "肖宝成"
console.log(modelName.userName);//肖宝成
console.log(modelName.age);//24
modelName.func();//func
console.log(modelName.sex)//男

9.4事例操作

9.4.1导出js文件

function show() {
    
    
    console.log('show')
}
function sum() {
    
    
    console.log('sum')
}

function People() {
    
    

}
People.prototype = {
    
    
    showName: function (something) {
    
    
        console.log(something)
    }
}
let a = 1;
let b = 2;
export {
    
    
    show,
    sum,
    a,
    b
}
let mod = {
    
    
    People
}
export default mod

9.4.2引入js文件

import mod, {
    
     show, sum, a, b } from '../../model/index-1.js'//相对路径
new mod.People().showName('工作');//工作
show();//show
sum();//sum
console.log(a)//1
console.log(b)//2

10类(class)和继承

10.0注意点

10.0.1关于[里面放变量名称]

let aaa = 'xbc';
let bbb = 'wyt';
function func(a, b) {
    
    
  return a + b;
}

let funcObj = {
    
    
  [func(aaa, bbb)]: '你好!'
};
console.log(funcObj);//{xbcwyt:"你好!"}

let json = {
    
    
  [aaa + bbb]: 'hello'
}
console.log(json);//{xbcwyt:"hello"}

10.0.2class没有预解析的功能

let p = new Person();//Uncaught ReferenceError: Cannot access 'Person' before initialization
class Person {
    
    
  constructor() {
    
    
    this.name = 996
  }
}

10.0.3矫正this

  • call(需要this指向的,参数一,参数二,参数三……)
  • apply(需要this指向的,[‘参数一’,‘参数二’,‘参数三’]……)//这两个都会自调用
  • bind(需要this指向的)//返回的是一个函数,需要手动调用
function func() {
    
    
  console.log(this);
};

func.call({
    
    })//{}
func.apply({
    
    })//{}
func.bind({
    
    })()//{}

class Person {
    
    
  constructor() {
    
    
    this.name = '李四'
    console.log(this)

  }
  showName() {
    
    
    return `名字${
      
      this.name}`
  }
}
let people = new Person();
let {
    
     showName } = people;//解构赋值
console.log(showName.bind(people)())//将本来指向window的this指向people

10.1class里面的取值函数(getter),存值函数(setter) 用的比较少

class Person {
    
    
  constructor() {
    
    
  }
  set name(value) {
    
    
      console.log('设置name属性为' + value)//设置name属性为张三
  }
  get name() {
    
    
      return `获取name的属性`;
  }
}
let people = new Person();//是一个对象
people.name = '张三';//给对象设置一个私有属性 设置的时候就会自己调用set name方法了
console.log(people.name)//获取name的属性 取得时候就会调用get name 方法了

10.2静态方法

class Person {
    
    
    constructor() {
    
    
    }
    showName() {
    
    
        return `这是showName方法`
    }
    static aaa(){
    
    //定义静态方法
        return '静态方法'
    }
}
let people = new Person();//是一个对象
console.log(people.showName())//这是showName方法
console.log(Person.aaa())//静态方法 //静态方法可以直接通过person调用,不用new

10.3使用函数模拟

10.3.1函数模拟类

function People(name = '张三', age = '18') {
    
    
  this.name = name;
  this.age = age
}
People.prototype = {
    
    
  constructor: People,
  skills: function (someThing = '技术支持') {
    
    
    console.log(`你好,我叫${
      
      this.name}今年${
      
      this.age}我会${
      
      someThing}`)
  }
};

function animal(name = '狮子', subject = '猫科') {
    
    
  this.name = name;
  this.subject = subject
}
// animal.prototype = {
    
    
//     life: function (where = '非洲大草原') {
    
    
//         console.log(`这是${this.name}所属${this.subject}生活在${where}`)
//     }
// }
Object.assign(animal.prototype, {
    
    //本质上都是往prototype上添加类
  life(where = '非洲大草原') {
    
    
    console.log(`这是${
      
      this.name}所属${
      
      this.subject}生活在${
      
      where}`)
  }
})

let p = new People('李四', 12);
let a = new animal('老虎', '虎类');
p.skills('跳舞');//你好,我叫李四今年12我会跳舞
a.life('东北森林');//这是老虎所属虎类生活在东北森林

10.3.2函数模拟类继承

function Person(name, age, sex) {
    
    
  this.name = name;
  this.age = age;
  this.sex = sex;
};

Person.prototype.showInfo = function () {
    
    
  return `我叫${
      
      this.name},性别${
      
      this.sex},今年${
      
      this.age}了`
};

function Child(name, age, sex, skill) {
    
    
  Person.call(this, name, age, sex);
  this.skill = skill;
};

Child.prototype = new Person();
Child.prototype.showSkill = function () {
    
    
  console.log(this.showInfo());//我叫张三,性别男,今年12了
  return `我叫${
      
      this.name},性别${
      
      this.sex},今年${
      
      this.age}了,技能${
      
      this.skill}`;
};

let c = new Child('张三', 12, '男', '前端开发');

console.log(c.showInfo());//我叫张三,性别男,今年12了
console.log(c.showSkill());//我叫张三,性别男,今年12了,技能前端开发

10.4使用类

class Person {
    
    
  constructor(name, age, sex) {
    
    
    this.name = name;
    this.age = age;
    this.sex = sex;
  }
  showInfo() {
    
    
    return `我叫${
      
      this.name},性别${
      
      this.sex},今年${
      
      this.age}了`
  }
};

let p = new Person('张三', 16, '男');
console.log(p.showInfo());//我叫张三,性别男,今年16了

10.5类继承

class Person {
    
    
  constructor(name, age) {
    
    
    this.name = name;
    this.age = age;
  }
  information(where) {
    
    
    console.log('父级的方法')
    return `你好,我叫${
      
      this.name}今年${
      
      this.age}岁了,我在${
      
      where}工作`
  }
}

class Student extends Person {
    
    //继承父类
  constructor(name, age, sex, workType) {
    
    
    super(name, age);//调用父类的属性
    this.sex = sex;
    this.workType = workType;
  }
  information1(where) {
    
    //当子类的名称和父类一致时,子类会覆盖父类的方法名称如果不想覆盖需要在子类中调用 super.Information()//然后在处理子类的逻辑即可
    return `你好,我叫${
      
      this.name}性别${
      
      this.sex}今年${
      
      this.age}岁了,我在${
      
      where}工作,工作岗位是${
      
      this.workType}`
  }
}
let student = new Student('张三', 26, '男', 'web开发工程师');
console.log(student.information('天津'))//你好,我叫张三今年26岁了,我在天津工作
console.log(student.information1('天津'))//你好,我叫张三性别男今年26岁了,我在天津工作,工作岗位是web开发工程师

10.6实例一:实现拖拽功能

class Drag {
    
    
  constructor(id) {
    
    
    this.id = document.querySelector(id);
    this.divInsideMouseX = 0;
    this.divInsideMouseY = 0;
    this.init();//自调用一下,也可以称之为初始化
  }
  init() {
    
    
    this.id.onmousedown = function (e) {
    
    
      e.preventDefault();//取消选中文字
      this.divInsideMouseX = e.clientX - this.id.offsetLeft;//获取鼠标在div内的位置
      this.divInsideMouseY = e.clientY - this.id.offsetTop;
      document.onmousemove = this.mouseMove.bind(this);
      document.onmouseup = this.mouseUp.bind(this)
    }.bind(this)//将this的指向由事件源指向Drag对象
  }
  mouseMove(e) {
    
    
    this.id.style.left = e.clientX - this.divInsideMouseX + 'px';
    this.id.style.top = e.clientY - this.divInsideMouseY + 'px';
  }
  mouseUp() {
    
    //当鼠标抬起的时候取消绑定事件
    document.onmousemove = null;
    document.onmouseup = null;
  }
}

new Drag('#div1');
class ChildrenDrag extends Drag {
    
    //子类继承父类
  //限制拖动的范围
  mouseMove(e) {
    
    //限制范围在move中就可以所以需要重写move
    super.mouseMove(e);//重写之前要调用父级
    if (this.id.offsetLeft < 0) {
    
    
      this.id.style.left = 0;
    }

    if (this.id.offsetLeft > document.documentElement.clientWidth - this.id.offsetWidth) {
    
    
      this.id.style.left = document.documentElement.clientWidth - this.id.offsetWidth + 'px';
    }

    if (this.id.offsetTop < 0) {
    
    
      this.id.style.top = 0;
    }
    if (this.id.offsetTop > document.documentElement.clientHeight - this.id.offsetHeight) {
    
    
      this.id.style.top = document.documentElement.clientHeight - this.id.offsetHeight + 'px';
    }
  }
}
new ChildrenDrag('#div2')

11.es6新增的数据类型symbol

  • 数据类型
数据类型={
    
    
	number,
	string,
	boolean,
	object,
	underfind,
	function,
	symbol//es6新加的数据类型,基本类型
}
  • 基本数据类型有这六种:undefined、null、string、number、boolean、symbol(es6)。
    引用类型有这几种:Object、Array、RegExp、Date、Function、特殊的基本包装类型(String、Number、Boolean)以及单体内置对象(Global、Math)。

11.1Symbol前面不能加new,加new报错因为Symbol并不是一个构造函数

let syml = Symbol('bbb');
console.log(syml);//Symbol(bbb)

11.2Symbol()返回的都是唯一值 一般做一个key,定义一些唯一或者私有的东西

let symbol = Symbol('name');
let json = {
    
    
  a: 'apple',
  b: 'banana',
  [symbol]: 'symbol'//可以作为一个唯一的key值
}
console.log(json.a)//apple
console.log(json['a'])//apple
console.log(json[symbol])//symbol

for (let [key, value] of Object.entries(json)) {
    
    //注意点:如果用symbol作为key值,是不能用for in循环出来的
  console.log(key, value)
  //a apple
  //index-1.js?0ad2:16 b banana
}

12.generator函数

12.1基本使用

function* gen() {
    
    //在function和函数名之间加一个*就代表是generator函数
  yield 'welcome';//yidle只能在这个函数内部使用
  yield 'to';
  return '牧马人!';
}
let genJson = gen()//返回的是一个generator对象

console.log(genJson.next())//{value: "welcome", done: false} done的意思就是完成没有,现在后面还有yield,所以是false
console.log(genJson.next())//{value: "to", done: false}
console.log(genJson.next())//{value: "牧马人!", done: true}
//上述调用,都是手动调用,十分麻烦 因为generator是一个迭代器,所以可以使用循环,但是只能使用for of循环

for (let value of genJson) {
    
    
  console.log(value)//注意点,遍历出来的只能是yield的东西,return是不能被遍历的
}

12.2generator配合解构赋值

function* gen() {
    
    
  yield 'welcome';
  yield 'to';
  return 'China';
};
let genJson = gen();
let [a, b, c] = genJson;//解构赋值,只能解构yield对应的值
console.log(a, b, c)//welcome to undefined

let [a, ...b] = genJson;//解构赋值,只能解构yield对应的值
console.log(a, b)//welcome ["to"]//这里面的a b 是随便定义的

console.log(...genJson)//welcome to

console.log(Array.from(gen()))//["welcome", "to"] 

12.3应用实例

function* gen() {
    
    
  let val = yield 'itstrive';
  yield axios({
    
    
    method: 'get',
    url: 'https://api.github.com/users/' + val
  })
}
let g1 = gen();
let userName = g1.next().value;
console.log(userName)//itstrive
console.log(g1.next(userName).value)//Promise 对象//所以能用then
g1.next(userName).value.then(res => {
    
    //
  console.log(res)//{data: {…}, status: 200, statusText: "OK", headers: {…}, config: {…}, …}
});

13.同步异步

  • 异步:不连续,上一个操作没有执行完毕,下一个操作照样可以开始
  • 同步:连续执行,上一个操作没有执行完毕,下一个操作不能开始
  • 关于异步,解决方案:
    • 回调函数的方案
    • 事件监听方式
    • 发布/订阅
    • Promise对象

13.1利用promise解决异步回调问题

const fs = require('fs');
//简单封装 将fs封装成一个promise版本
const readFile = function (fileName) {
    
    
  return new Promise((resolve, reject) => {
    
    //新建一个promise对象并返回出去
    fs.readFile(fileName, (err, data) => {
    
    //接收文件名
      if (err) reject(err);//如果报错
      resolve(data);//成功
    })
  })
}
//promise
readFile('data/a.txt').then(res => {
    
    //将文件路径传到函数中,并调用then
  console.log(res.toString());//aaaaaaaaaaa
  return readFile('data/b.txt');// 将文件路径传到函数中
}).then(res => {
    
    
  console.log(res.toString());//bbbbbbbbbbbb
  return readFile('data/c.txt') //将文件路径传到函数中
}).then(res => {
    
    
  console.log(res.toString());//cccccccccccccccccc
})

13.2利用generator解决异步问题

const fs = require('fs');
//简单封装 将fs封装成一个promise版本
const readFile = function (fileName) {
    
    
  return new Promise((resolve, reject) => {
    
    
    fs.readFile(fileName, (err, data) => {
    
    
      if (err) reject(err);
      resolve(data);
    })
  })
}
//generator
function* gen() {
    
    //将所有的文件路径都放在gen中
  yield readFile('data/a.txt');
  yield readFile('data/b.txt');
  yield readFile('data/c.txt');
}
let g1 = gen();
g1.next().value.then(res => {
    
    
  console.log(res.toString())//aaaaaaaaaaa
  return g1.next().value//返回promise对象
}).then(res => {
    
    
  console.log(res.toString())//bbbbbbbbbbbb
  return g1.next().value;
}).then(res => {
    
    
  console.log(res.toString())//cccccccccccccccccc
})

13.3利用async处理异步函数

const fs = require('fs');
//简单封装 将fs封装成一个promise版本
const readFile = function (fileName) {
    
    
  return new Promise((resolve, reject) => {
    
    
    fs.readFile(fileName, (err, data) => {
    
    
      if (err) reject(err);
      resolve(data);
    })
  })
}
//asyns
async function fn() {
    
     //asyns表明这是一个异步函数 await意思是,当程序执行到这里的时候需要等待,直到加载在往下走
  let f1 = await readFile('data/a.txt')
  console.log(f1.toString());//aaaaaaaaaaa //自动调用
  let f2 = await readFile('data/b.txt')
  console.log(f2.toString());//bbbbbbbbbbbb
  let f3 = await readFile('data/c.txt')
  console.log(f3.toString());//cccccccccccccccccc
}
fn();

13.4asyns特点

asyns function func(){
    
    //表示异步,这个函数里面有异步的任务
	let result=await xxx//表示结果需要等待
}
  • await只能放到asyns中
  • 语义化更强了
  • await后面可以是promise对象,也可以是数字,字符串,布尔
  • asyns函数返回的是一个promise对象

13.5async基本使用

async function func() {
    
    
  return '你好'
};

console.log(func());//Promise {<fulfilled>: "你好"}
func().then(res => {
    
    
  console.log(res);//你好
})

13.6await语句后面promise状态变成reject,那么整个async函数就会中断执行

async function func() {
    
    
  let res1 = await Promise.reject('出bug了');
  console.log(res1);//'出bug了'
  let res2 = await Promise.resolve('success');
  console.log(res2);//中断
  let res3 = await Promise.resolve('success');
  console.log(res3);//中断
};
func();

13.7不想当一个函数出现问题时,就中断整个请求,就需要用到try和catch

async function func() {
    
    
  try {
    
    
    let res1 = await Promise.reject('出bug了');
    console.log(res1);//'出bug了'
  } catch (e) {
    
    
  }
  try {
    
    
    let res2 = await Promise.reject('出bug了');
    console.log(res2);//success
  } catch (e) {
    
    

  }
  try {
    
    
    let res3 = await Promise.resolve('success');
    console.log(res3);//success
  } catch (e) {
    
    

  }
};
func();

13.8利用promise本身的catch解决

async function func() {
    
    
  let res1 = await Promise.reject('出bug了').catch(res => {
    
    
    console.log(res);//'出bug了'
  })
  console.log(res1);//undefined

  let res2 = await Promise.reject('出bug了').catch(res => {
    
    
    console.log(res);//出bug了
  })
  console.log(res2);//undefined

  let res3 = await Promise.resolve('success').catch(res => {
    
    
    console.log(res);
  })
  console.log(res3);//success
};
func();

13.9任何有await地方都有需要catch掉

async function func() {
    
    
  try {
    
    
    let res = await axios({
    
    
      method: 'get',
      url: 'http://jsonplaceholder.typicode.com/posts'
    })
    let res1 = await axios({
    
    
      method: 'get',
      url: 'http://jsonplaceholder.typicode.com/posts/1'
    })

    console.log(res1);
    console.log(res);
  } catch (e) {
    
     }
  try {
    
    

  } catch (e) {
    
     }
};
func();

猜你喜欢

转载自blog.csdn.net/big_sun_962464/article/details/113486423