<!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>
</head>
<body>
<script>
//认识箭头函数
// const add =(x,y)=>{
// return x+y;
// }
// console.log((add(1,1)))
//箭头函数的结构
//const/let 函数名=参数=>函数体
// 3,如何将一般函数改写成箭头函数
// 声明形式
// function add(){}
// 声明形式
// const add=function (){}
//函数表达式形式=>箭头函数
//箭头函数 的注意事项
// 1.单个参数
// 单个参数可以省略圆括号
// const add = x => {
// return x + 1;
// };
// console.log(add(1));
// 无参数或多个参数不能省略圆括号
// const add = () => {
// return 1 + 1;
// };
// const add = (x, y) => {
// return x + y;
// };
// console.log(add(1, 1));
// 2.单行函数体
// 单行函数体可以同时省略 {} 和 return
// const add = (x, y) => {
// return x + y;
// };
// const add = (x, y) => x + y;
// console.log(add(1, 1));
// 多行函数体不能再化简了
// const add = (x, y) => {
// const sum = x + y;
// return sum;
// };
// 3.单行对象
// const add = (x, y) => {
// return {
// value: x + y
// };
// };
// const add = (x, y) => ({
// value: x + y
// });
// 如果箭头函数返回单行对象,可以在 {} 外面加上 (),让浏览器不再认为那是函数体的花括号
// const add = (x, y) => [x, y];
// console.log(add(1, 1));
//非箭头函数中的 this 指向
// 1.全局作用域中的 this 指向
// console.log(this); // window
// 2.一般函数(非箭头函数)中的 this 指向
// 'use strict';
// function add() {
// console.log(this);
// }
// 严格模式就指向 undefined
// add(); // undefined->window(非严格模式下)
// window.add();
// const calc = {
// add: add
// };
// // calc.add(); // calc
// const adder = calc.add;
// adder(); // undefined->window(非严格模式下)
// document.onclick = function () {
// console.log(this);
// };
// document.onclick();
// function Person(username) {
// this.username = username;
// console.log(this);
// }
// const p = new Person('Alex');
// 只有在函数调用的时候 this 指向才确定,不调用的时候,不知道指向谁
// this 指向和函数在哪儿调用没关系,只和谁在调用有关
// 没有具体调用对象的话,this 指向 undefined,在非严格模式下,转向 window
// 箭头函数中的 this 指向
// 1.箭头函数中的 this 指向
// 箭头函数没有自己的 this
// const calc = {
// add: () => {
// console.log(this);
// }
// };
// calc.add(); // window
// 2.练习
// 'use strict';
// const calc = {
// add: function () {
// this
// const adder = () => {
// console.log(this);
// };
// adder();
// }
// };
// calc.add(); // calc
// const addFn = calc.add;
// addFn(); // undefined->window
// 不适用箭头函数的场景
// 1.作为构造函数
// 箭头函数没有 this
// const Person = () => {};
// new Person();
// 2.需要 this 指向调用对象的时候
// document.onclick = function () {
// console.log(this);
// };
// document.addEventListener(
// 'click',
// () => {
// console.log(this); //window
// },
// false
// );
// 3.需要使用 arguments 的时候
// 箭头函数中没有 arguments
// function add() {
// console.log(arguments);
// }
// add(1, 2,3,4,5);
// const add = () => console.log(arguments);
// add();
// 剩余参数
// 模板字符串
// 1.认识模板字符串
// const username1 = 'alex';
// // "alex"
// const username2 = `alex`;
// console.log(username1, username2, username1 === username2);
// 2.模板字符串与一般字符串的区别
// const person = {
// username: 'Alex',
// age: 18,
// sex: 'male'
// };
// const info =
// '我的名字是:' +
// person.username +
// ', 性别:' +
// person.sex +
// ', 今年' +
// person.age +
// '岁了';
// console.log(info);
// const info = `我的名字是:${person.username}, 性别:${person.sex}, 今年${person.age}岁了`;
// console.log(info);
// 和其他东西一起使用的时候,使用模板字符串,方便注入
// 其他情况下使用模板字符串或一般字符串都行
// 模板字符串的注意事项
// 1.输出多行字符串
// 一般字符串
// const info = '第1行\n第2行';
// console.log(info);
// 模板字符串
// const info = `第1行\n第2行`;
// const info = `第1行
// 第2行`;
// console.log(info);
// 模板字符串中,所有的空格、换行或缩进都会被保留在输出之中
// 2.输出 ` 和 \ 等特殊字符
// const info = `'\`\\`;
// console.log(info);
// 3.模板字符串的注入
// ${}
// const username = 'alex';
// const person = { age: 18, sex: 'male' };
// const getSex = function (sex) {
// return sex === 'male' ? '男' : '女';
// };
// const info = `${username}, ${person.age + 2}, ${getSex(person.sex)}`;
// console.log(info);
// 只要最终可以得出一个值的就可以通过 ${} 注入到模板字符串中
// 对象解构赋值的原理
// 1.模式(结构)匹配
// {}={}
// 2.属性名相同的完成赋值
// const { age, username } = { username: 'Alex', age: 18 };
// const { age: age, username: username } = { username: 'Alex', age: 18 };
// console.log(age, username);
// 取别名
// const { age: age, username: uname } = { username: 'Alex', age: 18 };
// console.log(age, uname);
// 对象解构赋值的注意事项
// 1.默认值的生效条件
// 对象的属性值严格等于 undefined 时,对应的默认值才会生效
// const { username = 'ZhangSan', age = 0 } = { username: 'alex' };
// console.log(username, age);
// 2.默认值表达式
// 如果默认值是表达式,默认值表达式是惰性求值的
// 3.将一个已经声明的变量用于解构赋值
// 如果将一个已经声明的变量用于对象的解构赋值,整个赋值需在圆括号中进行
// let { x } = { x: 1 };
// console.log(x);
// let x = 2;
// // ({ x } = { x: 1 });
// [x] = [1];
// console.log(x);
// 4.可以取到继承的属性
// const { a = 1} = {};
// const { toString } = {};
// console.log(toString);
// Object.prototype
// console.log(Object.prototype);
// console.log({});
// 1.函数参数的解构赋值
// const logPersonInfo = user => console.log(user.username, user.age);
// const logPersonInfo = ({ age = 0, username = 'ZhangSan' }) =>
// console.log(username, age);
// // logPersonInfo({ username: 'alex', age: 18 });
// logPersonInfo({});
// // { age, username:username }={ username: 'alex', age: 18 }
// 2.复杂的嵌套
// const obj = {
// x: 1,
// y: [2, 3, 4],
// z: {
// a: 5,
// b: 6
// }
// };
// const { x, y, z } = obj;
// console.log(x, y, z);
// const {
// y,
// y: [, yy],
// z,
// z: { b }
// } = obj;
// console.log(yy, y, z, b);
// [, yy] = [2, 3, 4]
//其他类型的解构赋值
// 1.字符串的解构赋值
// ''='hello' ×
// 数组形式的解构赋值
// const [a, b, , , c] = 'hello';
// console.log(a, b, c);
// 对象形式的解构赋值
// const { 0: a, 1: b, length } = 'hello';
// console.log(a, b, length);
// console.log('hello'.length);
// 字符串既可以按数组形式来解构赋值,也可以按对象形式来解构赋值
// 2.数值和布尔值的解构赋值
// 先将等号右边的值转为对象
// console.log(new Number(123));
// const { a = 1, toString } = 123;
// console.log(a, toString);
// const { b = 2, toString } = true;
// console.log(b, toString);
// 3.undefined 和 null 的解构赋值
// 由于 undefined 和 null 无法转为对象,所以对它们进行解构赋值,都会报错
// const { toString } = undefined;
// const { toString } = null;
//数组的解构赋值
// 1.认识解构赋值
// const arr = [1, 2, 3];
// const a = arr[0];
// const b = arr[1];
// const c = arr[2];
// console.log(a, b, c);
// const [a, b, c] = [1, 2, 3];
// console.log(a, b, c);
// 2.什么是解构赋值
// 解析某一数据的结构,将我们想要的东西提取出来,赋值给变量或常量
//数组解构赋值的原理
// 1.模式(结构)匹配
// [] = [1, 2, 3];
// 2.索引值相同的完成赋值
// const [a, b, c] = [1, 2, 3];
// console.log(a, b, c);
// 不取的,可以直接用逗号跳过
// const [a, [, , b], c] = [1, [2, 4, 5], 3];
// console.log(a, b, c);
//数组解构赋值的默认值
// 1.默认值的基本用法
// const [a, b] = [];
// const [a, b] = [undefined, undefined];
// const [a = 1, b = 2] = [];
// console.log(a, b);
// 2.默认值的生效条件
// 只有当一个数组成员严格等于(===)undefined 时,对应的默认值才会生效
// const [a = 1, b = 2] = [3, 0];
// const [a = 1, b = 2] = [3, null];
// const [a = 1, b = 2] = [3];
// console.log(a, b);
// 3.默认值表达式
// 如果默认值是表达式,默认值表达式是惰性求值的
// const func = () => {
// console.log('我被执行了');
// return 2;
// };
// // const [x = func()] = [1];
// const [x = func()] = [];
// console.log(x);
// 数组解构赋值的应用
// 1.常见的类数组的解构赋值
// arguments
// function func() {
// // console.log(arguments);
// // console.log(arguments.push);
// const [a, b] = arguments;
// console.log(a, b);
// }
// // func();
// func(1, 2);
// NodeList
// console.log(document.querySelectorAll('p'));
// const [p1, p2, p3] = document.querySelectorAll('p');
// console.log(p1, p2, p3);
// 2.函数参数的解构赋值
// const array = [1, 1];
// // const add = arr => arr[0] + arr[1];
// const add = ([x = 0, y = 0]) => x + y;
// // console.log(add(array));
// console.log(add([]));
// [x,y]=[1,1]
// 3.交换变量的值
// let x = 1;
// let y = 2;
// let tmp = x;
// x = y;
// y = tmp;
// console.log(x, y);
// [x, y] = [y, x];
// [x, y] = [2, 1];
// console.log(x, y);
// 函数参数
// 1.认识函数参数的默认值
// 调用函数的时候传参了,就用传递的参数;如果没传参,就用默认值
// multiply(2, 1);
// multiply(2);
// 2.函数参数默认值的基本用法
// const multiply = (x, y) => {
// if (typeof y === 'undefined') {
// y = 1;
// }
// return x * y;
// };
// const multiply = (x, y = 1) => x * y;
// console.log(multiply(2));
// 函数参数默认值的注意事项
// 1.默认值的生效条件
// 不传参数,或者明确的传递 undefined 作为参数,只有这两种情况下,默认值才会生效
// const multiply = (x, y = 1) => x * y;
// // console.log(multiply(2, 0));
// // console.log(multiply(2, null));
// console.log(multiply(2, undefined));
// console.log(multiply(2));
// 2.默认值表达式
// 如果默认值是表达式,默认值表达式是惰性求值的
// 3.设置默认值的小技巧
// 函数参数的默认值,最好从参数列表的右边开始设置
// const multiply = (x = 1, y) => x * y;
// console.log(multiply(undefined, 2));
// const multiply = (x, y = 1) => x * y;
// console.log(multiply(2));
// 函数参数默认值的应用
// 1.接收很多参数的时候
// const logUser = (username = 'ZhangSan', age = 0, sex = 'male') =>
// console.log(username, age, sex);
// logUser('Alex', 18, 'male');
// logUser();
// 2.接收一个对象作为参数
// const logUser = options =>
// console.log(options.username, options.age, options.sex);
// const logUser = ({ username = 'zhangsan', age = 0, sex = 'male' } = {}) =>
// console.log(username, age, sex);
// logUser({
// username: 'alex',
// age: 18,
// sex: 'male'
// });
// logUser({ username: 'alex' });
// { username = 'zhangsan', age = 0, sex = 'male' } = { username: 'alex' }
// logUser({});
// logUser();
// { username = 'zhangsan', age = 0, sex = 'male' } = {}
// { username = 'zhangsan', age = 0, sex = 'male' } = undefined
// 属性和方法的简洁表示
// 1.对象字面量是什么
// 实例化构造函数生成对象
// const person = new Object();
// person.age = 18;
// person.speak = function () {};
// 对象字面量
// const person = {
// age: 18,
// speak: function () {}
// };
// 2.属性的简洁表示法
// 键名和变量或常量名一样的时候,可以只写一个
// const age = 18;
// const person = {
// // age: age
// age
// };
// console.log(person);
// 3.方法的简洁表示法
// 方法可以省略冒号和 function 关键字
// const person = {
// speak: function () {}
// speak() {}
// };
// console.log(person);
// 方括号语法的用法
// 1.方括号语法的用法
// const prop = 'age';
// const person = {};
// // person.prop = 18;
// person[prop] = 18;
// 方括号语法可以写在对象字面量中
// const person = {
// [prop]: 18
// };
// console.log(person);
// 2.方括号中可以放什么
// ${}
// [值或通过计算可以得到值的(表达式)]
// const prop = 'age';
// const func = () => 'age2';
// const person = {
// // [prop]: 18
// // [func()]: 18
// // ['sex']: 'male'
// ['s' + 'ex']: 'male'
// };
// console.log(person);
// 3.方括号语法和点语法的区别
// 点语法是方括号语法的特殊形式
// const person = {};
// person.age 等价于 person['age']
// 属性名由数字、字母、下划线以及 $ 构成,并且数字还不能打头的时候可以使用点语法
// age18_$ √
// 18age ×
// 合法标识符可以用来作为变量或常量名
// 当你的属性或方法名是合法标识符时,可以使用点语法,其他情况下请使用方括号语法
// 展开运算符
// 数组认识展开运算符
// [3, 1, 2];
// Math.min
// console.log(Math.min([3, 1, 2]));
// console.log(Math.min(3, 1, 2));
// [3, 1, 2]->3, 1, 2
// 2.数组展开运算符的基本用法
// console.log(Math.min(...[3, 1, 2]));
// 相当于
// console.log(Math.min(3, 1, 2));
// 区分剩余参数和展开运算符
// 区分剩余参数和展开运算符
// 1.根本区别
// 展开运算符
// [3,1,2]->3,1,2
// 剩余参数
// 3,1,2->[3,1,2]
// 2.区分剩余参数和展开运算符
// 剩余参数
// const add = (...args) => {
// // console.log(args);
// // 展开运算符
// // console.log(...args);
// // console.log(...[1, 2, 3]);
// console.log(1, 2, 3);
// };
// add(1, 2, 3);
// console.log([...[1, 2, 3], 4]);
// [1, 2, 3]->1,2,3
// 数组展开运算符的应用
// 1.复制数组
// const a = [1, 2];
// // const b = a;
// // a[0] = 3;
// // console.log(b);
// const c = [...a];
// // const c = [1, 2];
// a[0] = 3;
// console.log(a);
// console.log(c);
// 2.合并数组
// const a = [1, 2];
// const b = [3];
// const c = [4, 5];
// // console.log([...a, ...b, ...c]);
// // console.log([...b, ...a, ...c]);
// console.log([1, ...b, 2, ...a, ...c, 3]);
// 3.字符串转为数组
// 字符串可以按照数组的形式展开
// console.log(...'alex');
// console.log('a', 'l', 'e', 'x');
// console.log([...'alex']);
// console.log('alex'.split(''));
// reverse
// 4.常见的类数组转化为数组
// arguments
// function func() {
// // console.log(arguments.push);
// console.log([...arguments]);
// }
// func(1, 2);
// NodeList
// console.log(document.querySelectorAll('p'));
// console.log([...document.querySelectorAll('p')].push);
// 剩余参数
// 剩余参数是什么
// 1.认识剩余参数
// const add = (x, y, z, ...args) => {};
// 2.剩余参数的本质
// const add = (x, y, ...args) => {
// console.log(x, y, args);
// };
// add();
// add(1);
// add(1, 2);
// add(1, 2, 3, 4, 5);
// 剩余参数永远是个数组,即使没有值,也是空数组
// 3, 4, 5->[3, 4, 5]
// 剩余参数的注意事项
// 1.箭头函数的剩余参数
// 箭头函数的参数部分即使只有一个剩余参数,也不能省略圆括号
// const add = (...args) => {};
// 2.使用剩余参数替代 arguments 获取实际参数
// const add = function () {
// console.log(arguments);
// };
// const add = (...args) => {
// console.log(args);
// };
// add(1, 2);
// 3.剩余参数的位置
// 剩余参数只能是最后一个参数,之后不能再有其他参数,否则会报错
// const add = (x, y, ...args) => {
// console.log(args);
// };
// 剩余参数的应用
// 1.完成 add 函数
// const add = (...args) => {
// let sum = 0;
// for (let i = 0; i < args.length; i++) {
// sum += args[i];
// }
// // reduce
// return sum;
// };
// // console.log(add());
// // console.log(add(1, 1));
// console.log(add(1, 2, 3));
// 2.与解构赋值结合使用
// 剩余参数不一定非要作为函数参数使用
// const [num, ...args] = [1, 2, 3, 4];
// 必须是最后一个
// const [...args,num] = [1, 2, 3, 4];
// console.log(num, args);
// const func = ([num, ...args]) => {};
// func([1, 2, 3]);
// const { x, y, ...z } = { a: 3, x: 1, y: 2, b: 4 };
// // 必须是最后一个
// // const { x, ...z, y } = { a: 3, x: 1, y: 2, b: 4 };
// console.log(x, y, z);
// const func = ({ x, y, ...z }) => {};
// func({ a: 3, x: 1, y: 2, b: 4 });
// 对象展开运算符的基本用法
// 1.展开对象
// 对象不能直接展开,必须在 {} 中展开
// const apple = {
// color: '红色',
// shape: '球形',
// taste: '甜'
// };
// console.log(...apple);
// console.log([...apple]);
// 对象的展开:把属性罗列出来,用逗号分隔,放到一个 {} 中,构成新对象
// console.log({ ...apple });
// console.log({ ...apple } === apple);
// 2.合并对象
// const apple = {
// color: '红色',
// shape: '球形',
// taste: '甜'
// };
// const pen = {
// color: '黑色',
// shape: '圆柱形',
// use: '写字'
// };
// console.log({ ...pen });
// console.log({ ...apple, ...pen });
// 新对象拥有全部属性,相同属性,后者覆盖前者
// console.log({ ...pen, ...apple });
// 相当于
// console.log({
// use: '写字',
// color: '红色',
// shape: '球形',
// taste: '甜'
// });
// console.log({ pen, apple });
// console.log({ ...pen, apple });
// 对象展开运算符的注意事项
// 1.空对象的展开
// 如果展开一个空对象,则没有任何效果
// console.log({ ...{} });
// console.log({ ...{}, a: 1 });
// 2.非对象的展开
// 如果展开的不是对象,则会自动将其转为对象,再将其属性罗列出来
// console.log({ ...1 });
// console.log(new Object(1));
// console.log({ ...undefined });
// console.log({ ...null });
// console.log({ ...true });
// 如果展开运算符后面是字符串,它会自动转成一个类似数组的对象,因此返回的不是空对象
// console.log({ ...'alex' });
// console.log([...'alex']);
// console.log(...'alex');
// console.log({ ...[1, 2, 3] });
// 3.对象中对象属性的展开
// 不会展开对象中的对象属性
// const apple = {
// feature: {
// taste: '甜'
// }
// };
// const pen = {
// feature: {
// color: '黑色',
// shape: '圆柱形'
// },
// use: '写字'
// };
// console.log({ ...apple });
// console.log({ ...apple, ...pen });
// 相当于
// console.log({
// feature: {
// color: '黑色',
// shape: '圆柱形'
// },
// use: '写字'
// });
// 对象展开运算符的应用
// 1.复制对象
// const a = { x: 1, y: 2 };
// // const b = a;
// const c = { ...a };
// console.log(c, c === a);
// 2.用户参数和默认参数
// add(1, 2);
// const logUser = ({
// username = 'ZhangSan',
// age = 0,
// sex = 'male'
// } = {}) => {
// console.log(username, age, sex);
// };
// const logUser = userParam => {
// const defaultParam = {
// username: 'ZhangSan',
// age: 0,
// sex: 'male'
// };
// const param = { ...defaultParam, ...userParam };
// const param = { ...defaultParam, ...undefined };
// console.log(param.username);
// const { username, age, sex } = { ...defaultParam, ...userParam }
// console.log(username, age, sex);
// };
// logUser();
// set和Map
// 1.什么是 Set
// 集合
// [1, 2];
// 数组是一系列有序的数据集合
// Set 是一系列无序、没有重复值的数据集合
// 2.理解 Set
// console.log([1, 2, 1]);
// console.log(new Array(1, 2, 1));
// const s = new Set();
// s.add(1);
// s.add(2);
// Set 中不能有重复的成员
// s.add(1);
// console.log(s);
// Set 没有下标去标示每一个值,所以 Set 是无序的,也不能像数组那样通过下标去访问 Set 的成员
// Set 实例的方法和属性
// 1.方法
// add
// const s = new Set();
// s.add(1).add(2).add(2);
// console.log(s);
// has
// console.log(s.has(1));
// console.log(s.has(3));
// delete
// s.delete(1);
// // 使用 delete 删除不存在的成员,什么都不会发生,也不会报错
// s.delete(3);
// console.log(s);
// clear
// s.clear();
// console.log(s);
// forEach
// s.forEach(function (value, key, set) {
// // Set 中 value = key
// console.log(value, key, set === s);
// // console.log(this);
// }, document);
// console.log(s);
// 按照成员添加进集合的顺序遍历
// 2.属性
// size
// console.log(s.size);
// console.log(s);
// Set 构造函数的参数
// 1.数组
// const s = new Set([1, 2, 1]);
// console.log(s);
// 2.字符串、arguments、NodeList、Set 等
// console.log(new Set('hi'));
// function func() {
// console.log(new Set(arguments));
// }
// func(1, 2, 1);
// console.log(new Set(document.querySelectorAll('p')));
// const s = new Set([1, 2, 1]);
// console.log(new Set(s) === s);
// console.log(s);
// Set 的注意事项
// 1.判断重复的方式
// const s = new Set([1, 2, 1]);
// const s = new Set([NaN, 2, NaN]);
// console.log(1 === 1);
// console.log(NaN === NaN);
// Set 对重复值的判断基本遵循严格相等(===)
// 但是对于 NaN 的判断与 === 不同,Set 中 NaN 等于 NaN
// console.log(s);
// const s = new Set();
// s.add({}).add({});
// console.log({} === {});
// console.log(s);
// 2.什么时候使用 Set
// ① 数组或字符串去重时
// ② 不需要通过下标访问,只需要遍历时
// ③ 为了使用 Set 提供的方法和属性时(add delete clear has forEach size 等)
// Set 的应用
// 1.数组去重
// [1, 2, 1];
// const s = new Set([1, 2, 1]);
// console.log(s);
// s.forEach
// console.log(...s);
// console.log([...s]);
// console.log([...new Set([1, 2, 1])]);
// 2.字符串去重
// 'abbacbd';
// const s = new Set('abbacbd');
// console.log([...s].join(''));
// console.log(s);
// console.log([...new Set('abbacbd')].join(''));
// 3.存放 DOM 元素
// console.log(document.querySelectorAll('p'));
// for()
// const s = new Set(document.querySelectorAll('p'));
// console.log(s);
// s.forEach(function (elem) {
// console.log(elem);
// elem.style.color = 'red';
// elem.style.backgroundColor = 'yellow';
// });
// Map 是什么
// 1.认识 Map
// 映射
// Map 和对象都是键值对的集合
// 键->值,key->value
// const person = {
// name: 'alex',
// age: 18
// };
// const m = new Map();
// m.set('name', 'alex');
// m.set('age', 18);
// console.log(m);
// 2.Map 和对象的区别
// 对象一般用字符串当作键
// const obj = {
// name: 'alex',
// true: 'true',
// [{}]: 'object'
// };
// console.log(obj);
// console.log({}.toString());
// 基本数据类型:数字、字符串、布尔值、undefined、null
// 引用数据类型:对象([]、{}、函数、Set、Map 等)
// 以上都可以作为 Map 的键
// const m = new Map();
// m.set('name', 'alex');
// m.set(true, 'true');
// m.set({}, 'object');
// m.set(new Set([1, 2]), 'set');
// m.set(undefined, 'undefined');
// console.log(m);
// Map 实例的属性和方法
// 1.方法
// set
// const m = new Map();
// 使用 set 添加的新成员,键如果已经存在,后添加的键值对覆盖已有
// m.set('age', 18).set(true, 'true').set('age', 20);
// console.log(m);
// set get
// add
// get
// console.log(m);
// console.log(m.get('age'));
// // get 获取不存在的成员,返回 undefined
// console.log(m.get('true'));
// console.log(m.get(true));
// has
// console.log(m.has('age'));
// console.log(m.has('true'));
// delete
// m.delete('age');
// m.delete('name');
// // 使用 delete 删除不存在的成员,什么都不会发生,也不会报错
// console.log(m);
// clear
// m.clear();
// console.log(m);
// forEach
// m.forEach(function (value, key, map) {
// // console.log(value, key, map === m);
// console.log(this);
// }, document);
// 2.属性
// size
// 对象没有类似的属性
// Map 构造函数的参数
// 1.数组
// console.log(new Map(['name', 'alex', 'age', 18]));
// 只能传二维数组,而且必须体现出键和值
// console.log(
// new Map([
// ['name', 'alex'],
// ['age', 18]
// ])
// );
// 2.Set、Map 等
// Set
// Set 中也必须体现出键和值
// const s = new Set([
// ['name', 'alex'],
// ['age', 18]
// ]);
// console.log(new Map(s));
// console.log(s);
// Map
// 复制了一个新的 Map
// const m1 = new Map([
// ['name', 'alex'],
// ['age', 18]
// ]);
// console.log(m1);
// const m2 = new Map(m1);
// console.log(m2, m2 === m1);
// Map 的注意事项
// 1.判断键名是否相同的方式
// 基本遵循严格相等(===)
// 例外就是 NaN,Map 中 NaN 也是等于 NaN
// console.log(NaN === NaN);
// const m = new Map();
// m.set(NaN, 1).set(NaN, 2);
// console.log(m);
// 2.什么时候使用 Map
// 如果只是需要 key -> value 的结构,或者需要字符串以外的值做键,使用 Map 更合适
// forEach for in
// size
// 只有模拟现实世界的实体时,才使用对象
// const person = {};
// 1.Iterator 的作用
// Iterator:遍历器(迭代器)
// for()
// [1,2].forEach
// new Set().forEach
// Iterator 也是用来遍历的
// 2.寻找 Iterator
// console.log(Iterator);
// console.log([1, 2][Symbol.iterator]());
// const it = [1, 2][Symbol.iterator]();
// console.log(it);
// 3.使用 Iterator
// const it = [1, 2][Symbol.iterator]();
// console.log(it.next()); // {value: 1, done: false}
// console.log(it.next()); // {value: 2, done: false}
// console.log(it.next()); // {value: undefined, done: true}
// console.log(it.next()); // {value: undefined, done: true}
// it:可遍历对象(可迭代对象)
// Symbol.iterator:可遍历对象的生成方法
// 4.什么是 Iterator
// Symbol.iterator(可遍历对象的生成方法) -> it(可遍历对象) -> it.next() -> it.next() -> ...(直到 done 为 true)
// 1.为什么需要 Iterator 遍历器
// 遍历数组:for 循环和 forEach 方法
// 遍历对象:for in 循环
// Iterator 遍历器是一个统一的遍历方式
// console.log([][Symbol.iterator]());
// console.log({}[Symbol.iterator]);
// 2.如何更方便的使用 Iterator
// Symbol.iterator->it->next()
// 我们一般不会直接使用 Iterator 去遍历
// for..of
// for...of 的用法
// 1.认识 for...of
// const arr = [1, 2, 3];
// // const it = arr[Symbol.iterator]();
// // // console.log(it.next());
// // // console.log(it.next());
// // // console.log(it.next());
// // // console.log(it.next());
// // let next = it.next();
// // console.log(next);
// // while (!next.done) {
// // console.log(next.value);
// // next = it.next();
// // console.log(next);
// // }
// for (const item of arr) {
// console.log(item);
// }
// // for...of 循环只会遍历出那些 done 为 false 时,对应的 value 值
// 2.与 break、continue 一起使用
// const arr = [1, 2, 3];
// for (const item of arr) {
// if (item === 2) {
// // break;
// continue;
// }
// console.log(item);
// }
// arr.forEach()
// 3.在 for...of 中取得数组的索引
// const arr = [1, 2, 3];
// keys() 得到的是索引的可遍历对象,可以遍历出索引值
// console.log(arr.keys());
// for (const key of arr.keys()) {
// // console.log(key);
// }
// // values() 得到的是值的可遍历对象,可以遍历出值
// for (const value of arr.values()) {
// console.log(value);
// }
// for (const value of arr) {
// console.log(value);
// }
// entries() 得到的是索引+值组成的数组的可遍历对象
// for (const entries of arr.entries()) {
// console.log(entries);
// }
// for (const [index, value] of arr.entries()) {
// console.log(index, value);
// }
// 原生可遍历和非原生可遍历
// 1.什么是可遍历
// 只要有 Symbol.iterator 方法,并且这个方法可以生成可遍历对象,
// 只要可遍历,就可以使用 for...of 循环来统一遍历
// 2.原生可遍历的有哪些
// 数组
// 字符串
// Set
// Map
// arguments
// NodeList
// for (const item of [1, 2, 3]) {
// console.log(item);
// }
// for (const item of 'hi') {
// console.log(item);
// }
// for (const item of new Set([1, 2])) {
// console.log(item);
// }
// for (const elem of document.querySelectorAll('p')) {
// console.log(elem);
// elem.style.color = 'red';
// }
// 3.非原生可遍历的有哪些
// 一般的对象
// const person = { sex: 'male', age: 18 };
// console.log(person[Symbol.iterator]());
// {next()} {value,done}
// person[Symbol.iterator] = () => {
// let index = 0;
// return {
// next() {
// index++;
// if (index === 1) {
// return {
// value: person.age,
// done: false
// };
// } else if (index === 2) {
// return {
// value: person.sex,
// done: false
// };
// } else {
// return {
// done: true
// };
// }
// }
// };
// };
// for (const item of person) {
// console.log(item);
// }
// for in
// 有 length 和索引属性的对象
// const obj = {
// '0': 'alex',
// '1': 'male',
// length: 2
// };
// obj[Symbol.iterator] = Array.prototype[Symbol.iterator];
// obj[Symbol.iterator] = () => {
// let index = 0;
// return {
// next() {
// let value, done;
// if (index < obj.length) {
// value = obj[index];
// done = false;
// } else {
// value = undefined;
// done = true;
// }
// index++;
// return {
// value,
// done
// };
// }
// };
// };
// for (const item of obj) {
// console.log(item);
// }
//使用了 Iterator 的场合
// 原生可遍历的
// Array 数组
// String 字符串
// Set
// Map
// 函数的 arguments 对象
// NodeList 对象
// for...of
// 1.数组的展开运算符
// console.log(...[1, 2, 3]);
// console.log(1, 2, 3);
// console.log(...'str');
// console.log(...new Set([1, 2, 3]));
// console.log(...{}); ×
// 2.数组的解构赋值
// const [a, b] = [1, 2];
// const [a, b] = [...[1, 2]];
// const [a, b] = 'hi';
// const [a, b] = [...'hi'];
// const [a, b] = [...new Set([3, 4])];
// console.log(a, b);
// 3.Set 和 Map 的构造函数
// new Set(iterator)
// new Map(iterator)
// 字符串新增的方法
// 判断字符串中是否含有某些字符
// 1.基本用法
// console.log('abc'.includes('a'));
// console.log('abc'.includes('ab'));
// console.log('abc'.includes('bc'));
// console.log('abc'.includes('ac')); // false
// 2.第二个参数
// 表示开始搜索的位置,默认是 0
// console.log('abc'.includes('a'));
// console.log('abc'.includes('a', 0));
// console.log('abc'.includes('a', 1)); // false
// 3.应用
// https://www.imooc.com/course/list
// https://www.imooc.com/course/list?c=fe&sort=pop&name=value
// let url = 'https://www.imooc.com/course/list?';
// const addURLParam = (url, name, value) => {
// url += url.includes('?') ? '&' : '?';
// url += `${name}=${value}`;
// return url;
// };
// url = addURLParam(url, 'c', 'fe');
// console.log(url);
// url = addURLParam(url, 'sort', 'pop');
// console.log(url);
// padStart() 和 padEnd()
// 补全字符串长度
// 1.基本用法
// console.log('x'.padStart(5, 'ab'));
// console.log('x'.padEnd(5, 'ab'));
// console.log('x'.padEnd(4, 'ab'));
// 2.注意事项
// 原字符串的长度,等于或大于最大长度,不会消减原字符串,字符串补全不生效,返回原字符串
// console.log('xxx'.padStart(2, 'ab'));
// console.log('xxx'.padEnd(2, 'ab'));
// 用来补全的字符串与原字符串长度之和超过了最大长度,截去超出位数的补全字符串,原字符串不动
// console.log('abc'.padStart(10, '0123456789'));
// console.log('abc'.padEnd(10, '0123456789'));
// 如果省略第二个参数,默认使用空格补全长度
// console.log('x'.padStart(4));
// console.log('x'.padEnd(4));
// 3.应用
// 显示日期格式
// 2020
// 10
// 10
// 2020-10-10
// 2020-01-01
// console.log('10'.padStart(2, 0));
// console.log('1'.padStart(2, 0));
// trimStart() 和 trimEnd()
// 清除字符串的首或尾空格,中间的空格不会清除
// 1.基本用法
// const s = ' a b c ';
// console.log(s);
// // console.log(s.trimStart());
// // console.log(s.trimLeft());
// // console.log(s.trimEnd());
// // console.log(s.trimRight());
// console.log(s.trim());
// 2.应用
// const usernameInput = document.getElementById('username');
// const btn = document.getElementById('btn');
// btn.addEventListener(
// 'click',
// () => {
// console.log(usernameInput.value);
// 验证
// console.log(usernameInput.value.trim());
// if (usernameInput.value.trim() !== '') {
// 可以提交
// console.log('可以提交');
// } else {
// 不能提交
// console.log('不能提交');
// }
// 手动提交
// },
// false
// );
//数组的方法
// 1.基本用法
// 判断数组中是否含有某个成员
// console.log([1, 2, 3].includes('2')); // false
// console.log([1, 2, 3].includes(2));
// 第二个参数表示搜索的起始位置,默认值是 0
// console.log([1, 2, 3].includes(2, 2));
// 基本遵循严格相等(===),但是对于 NaN 的判断与 === 不同,includes 认为 NaN === NaN
// console.log(NaN === NaN);
// console.log([1, 2, NaN].includes(NaN));
// 2.应用
// 去重
// [1, 2, 1];
// const arr = [];
// for (const item of [1, 2, 1]) {
// if (!arr.includes(item)) {
// arr.push(item);
// }
// }
// console.log(arr);
// Array.from()
// 将其他数据类型转换成数组
// 1.基本用法
// console.log(Array.from('str'));
// 2.哪些可以通过 Array.from() 转换成数组
// 2.1.所有可遍历的
// 数组、字符串、Set、Map、NodeList、arguments
// console.log(Array.from(new Set([1, 2, 1])));
// console.log([...new Set([1, 2, 1])]);
// 2.2.拥有 length 属性的任意对象
// const obj = {
// '0': 'a',
// '1': 'b',
// name: 'Alex',
// length: 3
// };
// console.log(Array.from(obj));
// console.log([...obj]); // ×
// 3.第二个参数
// 作用类似于数组的 map 方法,用来对每个元素进行处理,将处理后的值放入返回的数组
// console.log(
// [1, 2].map(value => {
// return value * 2;
// })
// );
// console.log(Array.from('12', value => value * 2));
// console.log(Array.from('12').map(value => value * 2));
// 4.第三个参数
// Array.from(
// '12',
// value => {
// console.log(this);
// },
// document
// );
// Array.from(
// '12',
// function () {
// console.log(this);
// },
// document
// );
// find() 和 findIndex()
// find():找到满足条件的一个立即返回
// findIndex():找到满足条件的一个,立即返回其索引
// 1.基本用法
// console.log(
// [1, 5, 10, 15].find((value, index, arr) => {
// // console.log(value, index, arr);
// console.log(this);
// return value > 9;
// }, document)
// );
// [1, 5, 10, 15].find(function (value, index, arr) {
// // console.log(value, index, arr);
// console.log(this);
// return value > 9;
// }, document);
// console.log(
// [1, 5, 10, 15].findIndex((value, index, arr) => {
// // console.log(value, index, arr);
// return value > 9;
// }, document)
// );
// 2.应用
// const students = [
// {
// name: '张三',
// sex: '男',
// age: 16
// },
// {
// name: '李四',
// sex: '女',
// age: 22
// },
// {
// name: '王二麻子',
// sex: '男',
// age: 32
// }
// ];
// console.log(students.find(value => value.sex === '女'));
// console.log(students.findIndex(value => value.sex === '女'));
// 对象的新增方法
// Object.assign()
// 用来合并对象
// 1.基本用法
// Object.assign(目标对象, 源对象1,源对象2,...): 目标对象
// const apple = {
// color: '红色',
// shape: '圆形',
// taste: '甜'
// };
// const pen = {
// color: '黑色',
// shape: '圆柱形',
// use: '写字'
// };
// console.log(Object.assign(apple, pen));
// Object.assign 直接合并到了第一个参数中,返回的就是合并后的对象
// console.log(apple);
// console.log(Object.assign(apple, pen) === apple);
// 可以合并多个对象
// console.log(Object.assign({}, apple, pen));
// console.log(apple);
// console.log({ ...apple, ...pen });
// 2.注意事项
// 2.1.基本数据类型作为源对象
// 与对象的展开类似,先转换成对象,再合并
// console.log(Object.assign({}, undefined));
// console.log(Object.assign({}, null));
// console.log(Object.assign({}, 1));
// console.log(Object.assign({}, true));
// console.log(Object.assign({}, 'str'));
// 2.2.同名属性的替换
// 后面的直接覆盖前面的
// const apple = {
// color: ['红色', '黄色'],
// shape: '圆形',
// taste: '甜'
// };
// const pen = {
// color: ['黑色', '银色'],
// shape: '圆柱形',
// use: '写字'
// };
// console.log(Object.assign({}, apple, pen));
// 3.应用
// 合并默认参数和用户参数
// const logUser = userOptions => {
// const DEFAULTS = {
// username: 'ZhangSan',
// age: 0,
// sex: 'male'
// };
// const options = Object.assign({}, DEFAULTS, userOptions);
// const options = Object.assign({}, DEFAULTS, undefined);
// console.log(options);
// };
// logUser();
// logUser({});
// logUser({ username: 'Alex' });
// Object.keys()、Object.values() 和 Object.entries()
// 1.基本用法
// const person = {
// name: 'Alex',
// age: 18
// };
// console.log(Object.keys(person));
// console.log(Object.values(person));
// console.log(Object.entries(person));
// 2.与数组类似方法的区别
// console.log([1, 2].keys());
// console.log([1, 2].values());
// console.log([1, 2].entries());
// console.log(person.keys);
// 数组的 keys()、values()、entries() 等方法是实例方法,返回的都是 Iterator
// 对象的 Object.keys()、Object.values()、Object.entries() 等方法是构造函数方法,返回的是数组
// 3.使用 for...of 循环遍历对象
// const person = {
// name: 'Alex',
// age: 18
// };
// for (const key of Object.keys(person)) {
// console.log(key);
// }
// for (const value of Object.values(person)) {
// console.log(value);
// }
// for (const entries of Object.entries(person)) {
// console.log(entries);
// }
// for (const [key, value] of Object.entries(person)) {
// console.log(key, value);
// }
// Object.keys()/values()/entires() 并不能保证顺序一定是你看到的样子,这一点和 for in 是一样的
// Promise
// 1.认识 Promise
// Promise 是异步操作的一种解决方案
// 回调函数
// document.addEventListener(
// 'click',
// () => {
// console.log('这里是异步的');
// },
// false
// );
// console.log('这里是同步的');
// 2.什么时候使用 Promise
// Promise 一般用来解决层层嵌套的回调函数(回调地狱 callback hell)的问题
// 运动
// const move = (el, { x = 0, y = 0 } = {}, end = () => {}) => {
// el.style.transform = `translate3d(${x}px, ${y}px, 0)`;
// el.addEventListener(
// 'transitionend',
// () => {
// console.log('end');
// end();
// },
// false
// );
// };
// const boxEl = document.getElementById('box');
// document.addEventListener(
// 'click',
// () => {
// move(boxEl, { x: 150 }, () => {
// move(boxEl, { x: 150, y: 150 }, () => {
// move(boxEl, { y: 150 }, () => {
// console.log('object');
// move(boxEl, { x: 0, y: 0 });
// });
// });
// });
// },
// false
// Promise 的基本用法
// 1.实例化构造函数生成实例对象
// console.log(Promise);
// Promise 解决的不是回调函数,而是回调地狱
// const p = new Promise(() => {});
// 2.Promise 的状态
// const p = new Promise((resolve, reject) => {
// // Promise 有 3 种状态,一开始是 pending(未完成),执行 resolve,变成 fulfilled(resolved),已成功
// // 执行 reject,变成 rejected,已失败
// // Promise 的状态一旦变化,就不会再改变了
// // pending->fulfilled
// // resolve();
// // pending->rejected
// reject();
// });
// 3.then 方法
// p.then(
// () => {
// console.log('success');
// },
// () => {
// console.log('error');
// }
// );
// 4.resolve 和 reject 函数的参数
// const p = new Promise((resolve, reject) => {
// Promise 有 3 种状态,一开始是 pending(未完成),执行 resolve,变成 fulfilled(resolved),已成功
// 执行 reject,变成 rejected,已失败
// Promise 的状态一旦变化,就不会再改变了
// pending->fulfilled
// resolve('succ');
// resolve({ username: 'alex' });
// pending->rejected
// reject('reason');
// reject(new Error('reason'));
// });
// p.then(
// data => {
// console.log('success', data);
// },
// err => {
// console.log('error', err);
// }
// );
// console.log(p);
// Promise 的注意事项
// 1.resolve 或 reject 函数执行后的代码
// 推荐在调用 resolve 或 reject 函数的时候加上 return,不再执行它们后面的代码
// new Promise((resolve, reject) => {
// // return resolve(123);
// return reject('reason');
// console.log('hi');
// });
// 2.Promise.all/race/allSettled 的参数问题
// 参数如果不是 Promise 数组,会将不是 Promise 的数组元素转变成 Promise 对象
// Promise.all([1, 2, 3]).then(datas => {
// console.log(datas);
// });
// 等价于
// Promise.all([
// Promise.resolve(1),
// Promise.resolve(2),
// Promise.resolve(3)
// ]).then(datas => {
// console.log(datas);
// });
// 不只是数组,任何可遍历的都可以作为参数
// 数组、字符串、Set、Map、NodeList、arguments
// Promise.all(new Set([1, 2, 3])).then(datas => {
// console.log(datas);
// });
// 3.Promise.all/race/allSettled 的错误处理
// const delay = ms => {
// return new Promise(resolve => {
// setTimeout(resolve, ms);
// });
// };
// const p1 = delay(1000).then(() => {
// console.log('p1 完成了');
// return 'p1';
// return Promise.reject('reason');
// });
// .catch(err => {
// console.log('p1', err);
// });
// const p2 = delay(2000).then(() => {
// console.log('p2 完成了');
// return 'p2';
// return Promise.reject('reason');
// });
// // .catch(err => {
// // console.log('p2', err);
// });
// const allPromise = Promise.all([p1, p2]);
// allPromise
// .then(datas => {
// console.log(datas);
// })
// .catch(err => console.log(err));
// 错误既可以单独处理,也可以统一处理
// 一旦被处理,就不会在其他地方再处理一遍
// Promise的应用
// 异步加载图片
// const loadImgAsync = url => {
// return new Promise((resolve, reject) => {
// const img = new Image();
// img.onload = () => {
// resolve(img);
// };
// img.onerror = () => {
// reject(new Error(`Could not load image at ${url}`));
// };
// img.src = url;
// });
// };
// const imgDOM = document.getElementById('img');
// loadImgAsync('https://2img.mukewang.com/5f057a6a0001f4f918720764.jpg')
// .then(img => {
// console.log(img.src);
// setTimeout(() => {
// imgDOM.src = img.src;
// }, 1000);
// })
// .catch(err => {
// console.log(err);
// });
// 1.什么时候执行
// pending->fulfilled 时,执行 then 的第一个回调函数
// pending->rejected 时,执行 then 的第二个回调函数
// 2.执行后的返回值
// then 方法执行后返回一个新的 Promise 对象
// const p = new Promise((resolve, reject) => {
// resolve();
// // reject();
// });
// const p2 = p
// .then(
// () => {},
// () => {}
// )
// .then()
// .then();
// console.log(p, p2, p === p2);
// 3.then 方法返回的 Promise 对象的状态改变
// const p = new Promise((resolve, reject) => {
// // resolve();
// reject();
// });
// p.then(
// () => {
// // console.log('success');
// },
// () => {
// console.log('err');
// // 在 then 的回调函数中,return 后面的东西,会用 Promise
// // return undefined;
// // 等价于
// // return new Promise(resolve => {
// // resolve(undefined);
// // });
// return 123;
// // return new Promise(resolve => {
// // resolve(123);
// // });
// // 默认返回的永远都是成功状态的 Promise 对象
// // return new Promise((resolve, reject) => {
// // reject('reason');
// // });
// }
// )
// .then(
// data => {
// console.log('success2', data);
// // return undefined;
// return new Promise(resolve => {
// resolve(undefined);
// });
// },
// err => {
// console.log('err2', err);
// }
// )
// .then(
// data => {
// console.log('success3', data);
// },
// err => {
// console.log('err3', err);
// }
// );
// 4.使用 Promise 解决回调地狱
// 运动
// const move = (el, { x = 0, y = 0 } = {}, end = () => {}) => {
// el.style.transform = `translate3d(${x}px, ${y}px, 0)`;
// el.addEventListener(
// 'transitionend',
// () => {
// end();
// },
// false
// );
// };
// const boxEl = document.getElementById('box');
// const movePromise = (el, point) => {
// return new Promise(resolve => {
// move(el, point, () => {
// resolve();
// });
// });
// };
// document.addEventListener(
// 'click',
// () => {
// movePromise(boxEl, { x: 150 })
// .then(() => {
// return movePromise(boxEl, { x: 0, y: 0 });
// })
// .then(() => {
// return movePromise(boxEl, { x: 150, y: 150 });
// })
// .then(() => {
// return movePromise(boxEl, { y: 150 });
// });
// },
// false
// );
// document.addEventListener(
// 'click',
// () => {
// move(boxEl, { x: 150 }, () => {
// move(boxEl, { x: 150, y: 150 }, () => {
// move(boxEl, { y: 150 }, () => {
// move(boxEl, { x: 0, y: 0 });
// });
// });
// });
// },
// false
// );
// catch()
// 1.有什么用
// then(
// data => {},
// err => {}
// );
// then(data => {});
// catch 专门用来处理 rejected 状态
// catch 本质上是 then 的特例
// then(null, err => {});
// 2.基本用法
// new Promise((resolve, reject) => {
// resolve(123);
// reject('reason');
// })
// .then(data => {
// console.log(data);
// })
// .then(null, err => {
// console.log(err);
// });
// .catch(err => {
// console.log(err);
// return undefined;
// throw new Error('reason');
// })
// .then(data => {
// console.log(data);
// })
// .catch(err => {
// console.log(err);
// });
// catch() 可以捕获它前面的错误
// 一般总是建议,Promise 对象后面要跟 catch 方法,这样可以处理 Promise 内部发生的错误
// finally()
// 1.什么时候执行
// 当 Promise 状态发生变化时,不论如何变化都会执行,不变化不执行
// new Promise((resolve, reject) => {
// // resolve(123);
// reject('reason');
// })
// .finally(data => {
// console.log(data);
// })
// .catch(err => {});
// 2.本质
// finally() 本质上是 then() 的特例
// new Promise((resolve, reject) => {
// // resolve(123);
// reject('reason');
// })
// .finally(data => {
// console.log(data);
// })
// .catch(err => {});
// 等同于
// new Promise((resolve, reject) => {
// resolve(123);
// reject('reason');
// })
// .then(
// result => {
// return result;
// },
// err => {
// return new Promise((resolve, reject) => {
// reject(err);
// });
// }
// )
// .then(data => {
// console.log(data);
// })
// .catch(err => {
// console.log(err);
// });
// Promise.resolve() 和 Promise.reject()
// 1.Promise.resolve()
// 是成功状态 Promise 的一种简写形式
// new Promise(resolve => resolve('foo'));
// // 简写
// Promise.resolve('foo');
// 参数
// 一般参数
// Promise.resolve('foo').then(data => {
// console.log(data);
// });
// Promise
// 当 Promise.resolve() 接收的是 Promise 对象时,直接返回这个 Promise 对象,什么都不做
// const p1 = new Promise(resolve => {
// setTimeout(resolve, 1000, '我执行了');
// // setTimeout(() => {
// // resolve('我执行了');
// // }, 1000);
// });
// Promise.resolve(p1).then(data => {
// console.log(data);
// });
// 等价于
// p1.then(data => {
// console.log(data);
// });
// console.log(Promise.resolve(p1) === p1);
// 当 resolve 函数接收的是 Promise 对象时,后面的 then 会根据传递的 Promise 对象的状态变化决定执行
// new Promise(resolve => resolve(p1)).then(data => {
// console.log(data);
// });
// 具有 then 方法的对象
// function func(obj) {
// obj.then(1, 2);
// }
// func({
// then(resolve, reject) {
// console.log(a, b);
// }
// });
// const thenable = {
// then(resolve, reject) {
// console.log('then');
// resolve('data');
// // reject('reason');
// }
// };
// Promise.resolve(thenable).then(
// data => console.log(data),
// err => console.log(err)
// );
// console.log(Promise.resolve(thenable));
// 2.Promise.reject()
// 失败状态 Promise 的一种简写形式
// new Promise((resolve, reject) => {
// reject('reason');
// });
// 等价于
// Promise.reject('reason');
// 参数
// 不管什么参数,都会原封不动地向后传递,作为后续方法的参数
// const p1 = new Promise(resolve => {
// setTimeout(resolve, 1000, '我执行了');
// });
// Promise.reject(p1).catch(err => console.log(err));
// new Promise((resolve, rejcet) => {
// resolve(123);
// })
// .then(data => {
// return data;
// return Promise.resolve(data);
// return Promise.reject('reason');
// })
// .then(data => {
// console.log(data);
// })
// .catch(err => console.log(err));
// Promise.all()
// 1.有什么用
// Promise.all() 关注多个 Promise 对象的状态变化
// 传入多个 Promise 实例,包装成一个新的 Promise 实例返回
// 2.基本用法
// const delay = ms => {
// return new Promise(resolve => {
// setTimeout(resolve, ms);
// });
// };
// const p1 = delay(1000).then(() => {
// console.log('p1 完成了');
// return 'p1';
// return Promise.reject('reason');
// });
// const p2 = delay(2000).then(() => {
// console.log('p2 完成了');
// return 'p2';
// return Promise.reject('reason');
// });
// Promise.all() 的状态变化与所有传入的 Promise 实例对象状态有关
// 所有状态都变成 resolved,最终的状态才会变成 resolved
// 只要有一个变成 rejected,最终的状态就变成 rejected
// const p = Promise.all([p1, p2]);
// p.then(
// data => {
// console.log(data);
// },
// err => {
// console.log(err);
// }
// );
// Promise.race() 和 Promise.allSettled()
// const delay = ms => {
// return new Promise(resolve => {
// setTimeout(resolve, ms);
// });
// };
// const p1 = delay(1000).then(() => {
// console.log('p1 完成了');
// return 'p1';
// return Promise.reject('reason');
// });
// const p2 = delay(2000).then(() => {
// console.log('p2 完成了');
// return 'p2';
// return Promise.reject('reason');
// });
// 1.Promise.race()
// Promise.race() 的状态取决于第一个完成的 Promise 实例对象,如果第一个完成的成功了,那
// const racePromise = Promise.race([p1, p2]);
// racePromise.then(
// data => {
// console.log(data);
// },
// err => {
// console.log(err);
// }
// );
// 2.Promise.allSettled()
// Promise.allSettled() 的状态与传入的Promise 状态无关
// 永远都是成功的
// 它只会忠实的记录下各个 Promise 的表现
// const allSettledPromise = Promise.allSettled([p1, p2]);
// allSettledPromise.then(data => {
// console.log('succ', data);
// });
// class类继承
// 1.认识 Class
// 人类:类
// 具体的人:实例、对象
// 类可以看做是对象的模板,用一个类可以创建出许多不同的对象
// 2.Class 的基本用法
// 类名一般大写
// class Person {} √
// class Person() {} ×
// class Person {}; ×
// function func() {}
// class Person {
// // 实例化时执行构造方法,所以必须有构造方法,但可以不写出来
// constructor(name, age) {
// // console.log('实例化时执行构造方法');
// this 代表实例对象,上面定义的是实例属性/方法
// this.name = name;
// this.age = age;
// // 一般在构造方法中定义属性,方法不在构造方法中定义
// // this.speak = () => {};
// }
// // speak:function(){}
// // 各实例共享的方法
// speak() {
// console.log('speak');
// }
// }
// // Person();
// const zs = new Person('ZS', 18);
// const ls = new Person('LS', 28);
// // console.log(zs.name);
// // console.log(zs.age);
// // console.log(zs.speak);
// zs.speak();
// // console.log(ls.name);
// // console.log(ls.age);
// // console.log(ls.speak);
// console.log(zs.speak === ls.speak);
// 3.Class 与构造函数
// class Person {
// constructor(name, age) {
// this.name = name;
// this.age = age;
// this.speak = () => {};
// }
// speak() {
// console.log('speak');
// }
// run(){}
// }
// Person.prototype.run = function () {};
// console.log(typeof Person);
// console.log(Person.prototype.speak);
// function Person(name, age) {
// this.name = name;
// this.age = age;
// // this.speak = () => {};
// }
// Person.prototype.speak = function () {};
// 实例属性、静态方法和静态属性
// 1.实例属性
// 方法就是值为函数的特殊属性
// class Person {
// age = 0;
// sex = 'male';
// getSex = function () {
// return this.sex;
// };
// constructor(name, sex) {
// this.name = name;
// // this.age = 18;
// this.sex = sex;
// }
// // speak() {
// // this.age = 18;
// // }
// }
// const p = new Person('Alex');
// console.log(p.name);
// console.log(p.age);
// 2.静态方法
// 类的方法
// class Person {
// constructor(name) {
// this.name = name;
// }
// speak() {
// console.log('speak');
// console.log(this);
// }
// // static speak() {
// // console.log('人类可以说话');
// // // this 指向类
// // console.log(this);
// // }
// }
// // Person.speak = function () {
// // console.log('人类可以说话');
// // console.log(this);
// // };
// const p = new Person('Alex');
// p.speak();
// Person.speak();
// 3.静态属性
// 类的属性
// class Person {
// constructor(name) {
// this.name = name;
// }
// 不要这么写,目前只是提案,有兼容性问题
// static version = '1.0';
// static getVersion() {
// return '1.0';
// }
// }
// Person.version = '1.0';
// const p = new Person('Alex');
// console.log(p.name);
// console.log(Person.version);
// console.log(Person.getVersion());
// 私有属性和方法
// 1.为什么需要私有属性和方法
// 一般情况下,类的属性和方法都是公开的
// 公有的属性和方法可以被外界修改,造成意想不到的错误
// class Person {
// constructor(name) {
// this.name = name;
// }
// speak() {
// console.log('speak');
// }
// getName() {
// return this.name;
// }
// }
// const p = new Person('Alex');
// console.log(p.name);
// p.speak();
// // ....
// p.name = 'zs';
// console.log(p.name);
// 2.模拟私有属性和方法
// 2.1._ 开头表示私有
// class Person {
// constructor(name) {
// this._name = name;
// }
// speak() {
// console.log('speak');
// }
// getName() {
// return this._name;
// }
// }
// const p = new Person('Alex');
// // console.log(p.name);
// p.name = 'zd';
// console.log(p.getName());
// 2.2.将私有属性和方法移出类
// (function () {
// let name = '';
// class Person {
// constructor(username) {
// this.name = name;
// name = username;
// }
// speak() {
// console.log('speak');
// }
// getName() {
// return name;
// }
// }
// window.Person = Person;
// })();
// (function () {
// const p = new Person('Alex');
// console.log(p.name);
// console.log(p.getName());
// })();
// class类继承
// 1.子类继承父类
// class Person {
// constructor(name, sex) {
// this.name = name;
// this.sex = sex;
// this.say = function () {
// console.log('say');
// };
// }
// speak() {
// console.log('speak');
// }
// static speak() {
// console.log('static speak');
// }
// }
// Person.version = '1.0';
// class Programmer extends Person {
// constructor(name, sex) {
// super(name, sex);
// }
// }
// const zs = new Programmer('zs', '男');
// console.log(zs.name);
// console.log(zs.sex);
// zs.say();
// zs.speak();
// Programmer.speak();
// console.log(Programmer.version);
// 2.改写继承的属性或方法
// class Programmer extends Person {
// constructor(name, sex, feature) {
// this.feature = feature; ×
// this 操作不能放在 super 前面
// super(name, sex);
// this.feature = feature;
// }
// hi() {
// console.log('hi');
// }
// 同名覆盖
// speak() {
// console.log('Programmer speak');
// }
// static speak() {
// console.log('Programmer static speak');
// }
// }
// Programmer.version = '2.0';
// const zs = new Programmer('zs', '男', '秃头');
// console.log(zs.name);
// console.log(zs.sex);
// console.log(zs.feature);
// zs.say();
// zs.speak();
// zs.hi();
// Programmer.speak();
// console.log(Programmer.version);
// super
// 1.作为函数调用
// 代表父类的构造方法,只能用在子类的构造方法中,用在其他地方就会报错
// super 虽然代表了父类的构造方法,但是内部的 this 指向子类的实例
// class Person {
// constructor(name) {
// this.name = name;
// console.log(this);
// }
// }
// class Programmer extends Person {
// constructor(name, sex) {
// super(name, sex);
// }
// // hi() {
// // super(); // ×
// // }
// }
// // new Person();
// new Programmer();
// 2.作为对象使用
// 2.1.在构造方法中使用或一般方法中使用
// super 代表父类的原型对象 Person.prototype
// 所以定义在父类实例上的方法或属性,是无法通过 super 调用的
// 通过 super 调用父类的方法时,方法内部的 this 指向当前的子类实例
// class Person {
// constructor(name) {
// this.name = name;
// console.log(this);
// }
// speak() {
// console.log('speak');
// // console.log(this);
// }
// static speak() {
// console.log('Person speak');
// console.log(this);
// }
// }
// class Programmer extends Person {
// constructor(name, sex) {
// super(name, sex);
// // console.log(super.name);
// // super.speak();
// }
// // hi() {
// // super(); // ×
// // }
// speak() {
// super.speak();
// console.log('Programmer speak');
// }
// // 2.2.在静态方法中使用
// // 指向父类,而不是父类的原型对象
// // 通过 super 调用父类的方法时,方法内部的 this 指向当前的子类,而不是子类的实例
// static speak() {
// super.speak();
// console.log('Programmer speak');
// }
// }
// // new Person();
// // new Programmer();
// Programmer.speak();
// 3.注意事项
// 使用 super 的时候,必须显式指定是作为函数还是作为对象使用,否则会报错
// class Person {
// constructor(name) {
// this.name = name;
// }
// speak() {
// console.log('speak');
// }
// }
// class Programmer extends Person {
// constructor(name, sex) {
// super(name, sex);
// console.log(super);
// console.log(super());
// console.log(super.speak);
// }
// }
// 1.前后端通信是什么
// 前端和后端数据交互的过程
// 浏览器和服务器之间数据交互的过程
// 2.后端向前端发送数据
// 访问页面
// 3.前端向后端发送数据
// 用户注册
// 1.前后端通信的过程
// 前后端的通信是在‘请求-响应’中完成的
// 2.概念解释
// 前端:浏览器端
// 客户端:只要能和服务器通信的就叫客户端
// 命令行工具
// curl https:www.imooc.com
// 后端:服务器端
// 1.使用浏览器访问网页
// 在浏览器地址栏输入网址,按下回车
// 2.HTML 的标签
// 浏览器在解析 HTML 标签的时候,遇到一些特殊的标签,会再次向服务器发送请求
// link/img/script/iframe
// 还有一些标签,浏览器解析的时候,不会向服务器发送请求,但是用户可以使用他们向服务器发
// a/form
// 3.Ajax 和 Fetch
// localStorage
// 1.localStorage 是什么
// localStorage 也是一种浏览器存储数据的方式(本地存储),它只是存储在本地,不会发送到服务器端
// 单个域名下的 localStorage 总大小有限制
// 2.在浏览器中操作 localStorage
// 3.localStorage 的基本用法
// console.log(localStorage);
// // setItem()
// localStorage.setItem('username', 'alex');
// localStorage.setItem('username', 'zs');
// localStorage.setItem('age', 18);
// localStorage.setItem('sex', 'male');
// // length
// // console.log(localStorage.length);
// // getItem()
// // console.log(localStorage.getItem('username'));
// // console.log(localStorage.getItem('age'));
// // // 获取不存在的返回 null
// // console.log(localStorage.getItem('name'));
// // removeItem()
// // localStorage.removeItem('username');
// // localStorage.removeItem('age');
// // // 删除不存在的 key,不报错
// // localStorage.removeItem('name');
// // clear()
// localStorage.clear();
// console.log(localStorage);
// 4.使用 localStorage 实现自动填充
// const loginForm = document.getElementById('login');
// const btn = document.getElementById('btn');
// const username = localStorage.getItem('username');
// if (username) {
// loginForm.username.value = username;
// }
// btn.addEventListener(
// 'click',
// e => {
// e.preventDefault();
// 数据验证
// console.log(loginForm.username.value);
// localStorage.setItem('username', loginForm.username.value);
// loginForm.submit();
// },
// false
// );
// localStorage 的注意事项
// 1.localStorage 的存储期限
// localStorage 是持久化的本地存储,除非手动清除(比如通过 js 删除,或者清除浏览器缓存),否则数据是永远不会过期的
// sessionStorage
// 当会话结束(比如关闭浏览器)的时候,sessionStorage 中的数据会被清空
// sessionStorage.setItem('username', 'alex');
// sessionStorage.getItem('username');
// sessionStorage.removeItem('username');
// sessionStorage.clear();
// 2.localStorage 键和值的类型
// localStorage 存储的键和值只能是字符串类型
// 不是字符串类型,也会先转化成字符串类型再存进去
// localStorage.setItem({}, 18);
// // localStorage.setItem('students', [{},{}]);
// console.log(
// typeof localStorage.getItem('[object Object]'),
// localStorage.getItem('[object Object]')
// );
// console.log({}.toString());
// 3.不同域名下能否共用 localStorage
// 不同的域名是不能共用 localStorage 的
// 4.localStorage 的兼容性
// IE7及以下版本不支持 localStorage,IE8 开始支持
// caniuse.com
// 1.Cookie 是什么
// Cookie 全称 HTTP Cookie,简称 Cookie
// 是浏览器存储数据的一种方式
// 因为存储在用户本地,而不是存储在服务器上,是本地存储
// 一般会自动随着浏览器每次请求发送到服务器端
// 2.Cookie 有什么用
// 利用 Cookie 跟踪统计用户访问该网站的习惯,比如什么时间访问,访问了哪些页面,在每个网页的停留时间等
// 3.在浏览器中操作 Cookie
// 不要在 Cookie 中保存密码等敏感信息
// Cookie 的基本用法
// 1.写入 Cookie
// document.cookie = 'username=zs';
// document.cookie = 'age=18';
// 不能一起设置,只能一个一个设置
// document.cookie = 'username=zs; age=18';
// 2.读取 Cookie
// console.log(document.cookie);
// 读取的是一个由名值对构成的字符串,每个名值对之间由“; ”(一个分号和一个空格)隔开
// username=zs; age=18
//Cookie 的属性
// 1.Cookie 的名称(Name)和值(Value)
// 最重要的两个属性,创建 Cookie 时必须填写,其它属性可以使用默认值
// Cookie 的名称或值如果包含非英文字母,则写入时需要使用 encodeURIComponent() 编码,读取时使用 decodeURIComponent() 解
// document.cookie = 'username=alex';
// document.cookie = `username=${encodeURIComponent('张三')}`;
// document.cookie = `${encodeURIComponent('用户名')}=${encodeURIComponent(
// '张三'
// )}`;
// 一般名称使用英文字母,不要用中文,值可以用中文,但是要编码
// 2.失效(到期)时间
// 对于失效的 Cookie,会被浏览器清除
// 如果没有设置失效(到期)时间,这样的 Cookie 称为会话 Cookie
// 它存在内存中,当会话结束,也就是浏览器关闭时,Cookie 消失
// document.cookie = 'username=alex';
// 想长时间存在,设置 Expires 或 Max-Age
// expires
// 值为 Date 类型
// document.cookie = `username=alex; expires=${new Date(
// '2100-1-01 00:00:00'
// )}`;
// max-age
// 值为数字,表示当前时间 + 多少秒后过期,单位是秒
// document.cookie = 'username=alex; max-age=5';
// document.cookie = `username=alex; max-age=${24 * 3600 * 30}`;
// 如果 max-age 的值是 0 或负数,则 Cookie 会被删除
// document.cookie = 'username=alex';
// document.cookie = 'username=alex; max-age=0';
// document.cookie = 'username=alex; max-age=-1';
// 3.Domain 域
// Domain 限定了访问 Cookie 的范围(不同域名)
// 使用 JS 只能读写当前域或父域的 Cookie,无法读写其他域的 Cookie
// document.cookie = 'username=alex; domain=www.imooc.com';
// www.imooc.com m.imooc.com 当前域
// 父域:.imooc.com
// 4.Path 路径
// Path 限定了访问 Cookie 的范围(同一个域名下)
// 使用 JS 只能读写当前路径和上级路径的 Cookie,无法读写下级路径的 Cookie
// document.cookie = 'username=alex; path=/course/list';
// document.cookie = 'username=alex; path=/1.Cookie/';
// 当 Name、Domain、Path 这 3 个字段都相同的时候,才是同一个 Cookie
// 5.HttpOnly
// 设置了 HttpOnly 属性的 Cookie 不能通过 JS 去访问
// 6.Secure 安全标志
// Secure 限定了只有在使用了 https 而不是 http 的情况下才可以发送给服务端
// Domain、Path、Secure 都要满足条件,还不能过期的 Cookie 才能随着请求发送到服务器端
// Cookie 的注意事项
// 1.前后端都可以创建 Cookie
// 2.Cookie 有数量限制
// 每个域名下的 Cookie 数量有限
// 当超过单个域名限制之后,再设置 Cookie,浏览器就会清除以前设置的 Cookie
// 3.Cookie 有大小限制
// 每个 Cookie 的存储容量很小,最多只有 4KB 左右
// 初识跨域
// 1.跨域是什么
// 同域,不是跨域
// const url = './index.html';
// http://127.0.0.1:5500
// 不同域,跨域,被浏览器阻止
// const url = 'https://www.imooc.com';
// const xhr = new XMLHttpRequest();
// Access to XMLHttpRequest at 'https://www.imooc.com/' from origin 'http://127.0.0.1:5
// 向一个域发送请求,如果要请求的域和当前域是不同域,就叫跨域
// 不同域之间的请求,就是跨域请求
// xhr.onreadystatechange = () => {
// if (xhr.readyState != 4) return;
// if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304) {
// console.log(xhr.responseText);
// }
// };
// xhr.open('GET', url, true);
// xhr.send(null);
// 2.什么是不同域,什么是同域
// https(协议)://www.imooc.com(域名):443(端口号)/course/list(路径)
// 协议、域名、端口号,任何一个不一样,就是不同域
// 与路径无关,路径一不一样无所谓
// 不同域
// https://www.imooc.com:443/course/list
// http://www.imooc.com:80/course/list
// http://www.imooc.com:80/course/list
// http://m.imooc.com:80/course/list
// http://imooc.com:80/course/list
// 同域
// http://imooc.com:80
// http://imooc.com:80/course/list
// 3.跨域请求为什么会被阻止
// 阻止跨域请求,其实是浏览器本身的一种安全策略--同源策略
// 其他客户端或者服务器都不存在跨域被阻止的问题
// 4.跨域解决方案
// ① CORS 跨域资源共享
// ② JSONP
// 优先使用 CORS 跨域资源共享,如果浏览器不支持 CORS 的话,再使用 JSONP
// CORS 跨域资源共享
// 1.CORS 是什么
// const url = 'https://www.imooc.com';
// const url = 'https://www.imooc.com/api/http/search/suggest?words=js';
// const xhr = new XMLHttpRequest();
// xhr.onreadystatechange = () => {
// if (xhr.readyState != 4) return;
// if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304) {
// console.log(xhr.responseText);
// }
// };
// xhr.open('GET', url, true);
// xhr.send(null);
// Access-Control-Allow-Origin: *
// 表明允许所有的域名来跨域请求它,* 是通配符,没有任何限制
// 只允许指定域名的跨域请求
// Access-Control-Allow-Origin: http://127.0.0.1:5500
// 2.使用 CORS 跨域的过程
// ① 浏览器发送请求
// ② 后端在响应头中添加 Access-Control-Allow-Origin 头信息
// ③ 浏览器接收到响应
// ④ 如果是同域下的请求,浏览器不会额外做什么,这次前后端通信就圆满完成了
// ⑤ 如果是跨域请求,浏览器会从响应头中查找是否允许跨域访问
// ⑥ 如果允许跨域,通信圆满完成
// ⑦ 如果没找到或不包含想要跨域的域名,就丢弃响应结果
// 3.CORS 的兼容性
// IE10 及以上版本的浏览器可以正常使用 CORS
// https://caniuse.com/
// JSONP
// 1.JSONP 的原理
// script 标签跨域不会被浏览器阻止
// JSONP 主要就是利用 script 标签,加载跨域文件
// 2.使用 JSONP 实现跨域
// 服务器端准备好 JSONP 接口
// https://www.imooc.com/api/http/jsonp?callback=handleResponse
// 手动加载 JSONP 接口或动态加载 JSONP 接口
// const script = document.createElement('script');
// script.src =
// 'https://www.imooc.com/api/http/jsonp?callback=handleResponse';
// document.body.appendChild(script);
// 声明函数
// const handleResponse = data => {
// console.log(data);
// };
// handleResponse({
// code: 200,
// data: [
// {
// word: 'jsp'
// },
// {
// word: 'js'
// },
// {
// word: 'json'
// },
// {
// word: 'js 入门'
// },
// {
// word: 'jstl'
// }
// ]
// });
// 优先使用 CORS,如果浏览器不支持 CORS 的话,再使用 JSONP
// </script>
<!-- <script src="https://www.imooc.com/api/http/jsonp?callback=handleResponse"></script> -
<!-- 相当于 -->
<!-- <script>
handleResponse({
code: 200,
data: [
{
word: 'jsp'
},
{
word: 'js'
},
{
word: 'json'
},
{
word: 'js 入门'
},
{
word: 'jstl'
}
]
});
</script> -->
<!-- 初识 Ajax -->
// 1.Ajax 是什么
// Ajax 是 Asynchronous JavaScript and XML(异步 JavaScript 和 XML)的简写
// Ajax 中的异步:可以异步地向服务器发送请求,在等待响应的过程中,不会阻塞当前页面,浏览器可以做自己
// XML(可扩展标记语言)是前后端数据通信时传输数据的一种格式
// XML 现在已经不怎么用了,现在比较常用的是 JSON
// Ajax 其实就是浏览器与服务器之间的一种异步通信方式
// 使用 Ajax 可以在不重新加载整个页面的情况下,对页面的某部分进行更新
// ① 慕课网注册检测
// ② 慕课网搜索提示
// 2.搭建 Ajax 开发环境
// Ajax 需要服务器环境,非服务器环境下,很多浏览器无法正常使用 Ajax
// Live Server
// windows phpStudy
// Mac MAMP
<!-- Ajax 的基本用法 -->
<!-- get请求 -->
<!-- <form action="https://www.imooc.com/api/http/search/suggest" method="get">
<input type="text" name="username" />
<input type="text" name="words" />
<input type="password" name="password" />
<input type="submit" value="提交" />
</form> -->
<script>
// 1.携带数据
// GET 请求不能通过请求体携带数据,但可以通过请求头携带
// const url =
// 'https://www.imooc.com/api/http/search/suggest?words=js&username=alex&age=18';
// const xhr = new XMLHttpRequest();
// xhr.onreadystatechange = () => {
// if (xhr.readyState != 4) return;
// if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304) {
// console.log(xhr.responseText);
// }
// };
// xhr.open('GET', url, true);
// xhr.send(null);
// 不会报错,但不会发送数据
// xhr.send('sex=male');
// 2.数据编码
// 如果携带的数据是非英文字母的话,比如说汉字,就需要编码之后再发送给后端,不然会造成乱码问题
// 可以使用 encodeURIComponent() 编码
// const url = `https://www.imooc.com/api/http/search/suggest?words=${encodeURIComponent(
// '前端'
// )}`;
// const xhr = new XMLHttpRequest();
// xhr.onreadystatechange = () => {
// if (xhr.readyState != 4) return;
// if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304) {
// console.log(xhr.responseText);
// }
// };
// xhr.open('GET', url, true);
// xhr.send(null);
// post请求
// 1.携带数据
// POST 请求主要通过请求体携带数据,同时也可以通过请求头携带
// const url = 'https://www.imooc.com/api/http/search/suggest?words=js';
// const xhr = new XMLHttpRequest();
// xhr.onreadystatechange = () => {
// if (xhr.readyState != 4) return;
// if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304) {
// console.log(xhr.responseText);
// }
// };
// xhr.open('POST', url, true);
// 如果想发送数据,直接写在 send() 的参数位置,一般是字符串
// xhr.send('username=alex&age=18');
// 不能直接传递对象,需要先将对象转换成字符串的形式
// xhr.send({
// username: 'alex',
// age: 18
// });
// [object Object]
// 2.数据编码
// xhr.send(`username=${encodeURIComponent('张三')}&age=18`);
// axios
// <!-- <script src="https://unpkg.com/axios/dist/axios.min.js"></script> -->
<!-- <script src="https://unpkg.com/axios@0.19.2/dist/axios.min.js"></script> -->
<script>
// 1.axios 是什么
// axios 是一个基于 Promise 的 HTTP 库,可以用在浏览器和 node.js 中
// 第三方 Ajax 库
// http://www.axios-js.com/zh-cn/docs/
// 2.axios 的基本用法
// 引入 axios
// console.log(axios);
const url = 'https://www.imooc.com/api/http/search/suggest?words=js';
// axios(url, {
// method: 'post',
// // 请求时的头信息
// headers: {
// 'Content-Type': 'application/x-www-form-urlencoded'
// // 'Content-Type': 'application/json'
// },
// // 通过请求头携带的数据
// params: {
// username: 'alex'
// },
// // 通过请求体携带的数据
// // application/json
// // data: {
// // age: 18,
// // sex: 'male'
// // }
// // application/x-www-form-urlencoded
// data: 'age=18&sex=male'
// // timeout: 10
// // withCredentials: true
// })
// .then(response => {
// console.log(response);
// console.log(response.data.data);
// })
// .catch(err => {
// console.log(err);
// });
// axios
// .get(url, {
// params: {
// username: 'alex'
// }
// })
// .then(response => {
// console.log(response);
// });
// axios
// .post(url, 'username=alex&age=18')
// .then(response => {
// console.log(response);
// })
// .catch(err => {
// console.log(err);
// });
// axios
// .post('https://www.imooc.com/api/http/json/search/suggest?words=js', {
// username: 'alex'
// })
// .then(response => {
// console.log(response);
// })
// .catch(err => {
// console.log(err);
// });
// axios.put()
// axios.delete()
// Fetch
// 1.Fetch 是什么
// Fetch 也是前后端通信的一种方式
// Fetch 是 Ajax(XMLHttpRequest)的一种替代方案,它是基于 Promise 的
// Ajax 的兼容性比 Fetch 好
// abort timeout
// 2.Fetch 的基本用法
// console.log(fetch);
// console.log(ajax);
// fetch() 调用后返回 Promise 对象
// const url = 'https://www.imooc.com/api/http/search/suggest?words=js';
// body: (...)
// bodyUsed: false
// ok: true
// status: 200
// statusText: "OK"
// type: "cors"
// url: "https://www.im
// 第二个参数是对象,用来配置 fetch
// const fd = new FormData();
// fd.append('username', 'alex');
// fetch(url, {
// method: 'post',
// body: null
// body: 'username=alex&age=18',
// body: JSON.stringify({ username: 'alex' })
// body: fd,
// headers: {
// // 'Content-Type': 'application/x-www-form-urlencoded'
// 'Content-Type': 'application/json'
// }
// mode: 'cors'
// credentials:'include'
// })
// .then(response => {
// console.log(response);
// body/bodyUsed
// body 只能读一次,读过之后就不让再读了
// ok
// 如果为 true,表示可以读取数据,不用再去判断 HTTP 状态码了
// if (response.ok) {
// console.log(response.json());
// return response.json();
// return response.text();
// } else {
// throw new Error(`HTTP CODE 异常 ${response.status}`);
// }
// })
// .then(data => {
// console.log(data);
// })
// .catch(err => {
// console.log(err);
// });
// JSON
// 1.JSON 是什么
// Ajax 发送和接收数据的一种格式
// XML
// username=alex&age=18
// JSON
// const url = 'https://www.imooc.com/api/http/search/suggest?words=js';
// const xhr = new XMLHttpRequest();
// xhr.onreadystatechange = () => {
// if (xhr.readyState != 4) return;
// if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304) {
// console.log(xhr.responseText);
// }
// };
// xhr.open('GET', url, true);
// xhr.send(null);
// {"code":200,"data":[{"word":"jsp"},{"word":"js"},{"word":"json"},{"word":"js \u5165\u95e8"}
// HTML/XML
// JSON 全称是 JavaScript Object Notation
// 2.为什么需要 JSON
// JSON 有 3 种形式,每种形式的写法都和 JS 中的数据类型很像,可以很轻松的和 JS 中的数据类型互
// JS->JSON->PHP/Java
// PHP/Java->JSON->JS
// JSON 的 3 种形式
// 1.简单值形式
// .json
// JSON 的简单值形式就对应着 JS 中的基础数据类型
// 数字、字符串、布尔值、null
// 注意事项
// ① JSON 中没有 undefined 值
// ② JSON 中的字符串必须使用双引号
// ③ JSON 中是不能注释的
// 2.对象形式
// JSON 的对象形式就对应着 JS 中的对象
// 注意事项
// JSON 中对象的属性名必须用双引号,属性值如果是字符串也必须用双引号
// JSON 中只要涉及到字符串,就必须使用双引号
// 不支持 undefined
// 3.数组形式
// JSON 的数组形式就对应着 JS 中的数组
// [1, "hi", null]
// 注意事项
// 数组中的字符串必须用双引号
// JSON 中只要涉及到字符串,就必须使用双引号
// 不支持 undefined
// const xhr = new XMLHttpRequest();
// xhr.onreadystatechange = () => {
// if (xhr.readyState != 4) return;
// if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304) {
// console.log(xhr.responseText);
// console.log(typeof xhr.responseText);
// }
// };
// xhr.open('GET', './plain.json', true);
// xhr.open('GET', './obj.json', true);
// xhr.open('GET', './arr.json', true);
// xhr.send(null);
// JSON 的常用方法
// 1.JSON.parse()
// JSON.parse() 可以将 JSON 格式的字符串解析成 JS 中的对应值
// 一定要是合法的 JSON 字符串,否则会报错
// const xhr = new XMLHttpRequest();
// xhr.onreadystatechange = () => {
// if (xhr.readyState != 4) return;
// if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304) {
// console.log(xhr.responseText);
// console.log(typeof xhr.responseText);
// console.log(JSON.parse(xhr.responseText));
// // console.log(JSON.parse(xhr.responseText).data);
// }
// };
// // xhr.open('GET', './plain.json', true);
// // xhr.open('GET', './obj.json', true);
// xhr.open('GET', './arr.json', true);
// // xhr.open(
// // 'GET',
// // 'https://www.imooc.com/api/http/search/suggest?words=js',
// // true
// // );
// xhr.send(null);
// 2.JSON.stringify()
// JSON.stringify() 可以将 JS 的基本数据类型、对象或者数组转换成 JSON 格式的字符串
// console.log(
// JSON.stringify({
// username: 'alex',
// age: 18
// })
// );
// const xhr = new XMLHttpRequest();
// xhr.open(
// 'POST',
// 'https://www.imooc.com/api/http/search/suggest?words=js',
// true
// );
// xhr.send(
// JSON.stringify({
// username: 'alex',
// age: 18
// })
// );
// 3.使用 JSON.parse() 和 JSON.stringify() 封装 localStorage
// import { get, set, remove, clear } from './storage.js';
// set('username', 'alex');
// console.log(get('username'));
// set('zs', {
// name: '张三',
// age: 18
// });
// console.log(get('zs'));
// remove('username');
// clear();
// XHR 的属性
// 1.responseType 和 response 属性
// const url = 'https://www.imooc.com/api/http/search/suggest?words=js';
// const xhr = new XMLHttpRequest();
// xhr.onreadystatechange = () => {
// if (xhr.readyState != 4) return;
// if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304) {
// // 文本形式的响应内容
// // responseText 只能在没有设置 responseType 或者 responseType = '' 或 'te
// // console.log('responseText:', xhr.responseText);
// // 可以用来替代 responseText
// console.log('response:', xhr.response);
// // console.log(JSON.parse(xhr.responseText));
// }
// };
// xhr.open('GET', url, true);
// // xhr.responseType = '';
// // xhr.responseType = 'text';
// xhr.responseType = 'json';
// xhr.send(null);
// IE6~9 不支持,IE10 开始支持
// 2.timeout 属性
// 设置请求的超时时间(单位 ms)
// const url = 'https://www.imooc.com/api/http/search/suggest?words=js';
// const xhr = new XMLHttpRequest();
// xhr.onreadystatechange = () => {
// if (xhr.readyState != 4) return;
// if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304) {
// console.log(xhr.response);
// }
// };
// xhr.open('GET', url, true);
// xhr.timeout = 10000;
// xhr.send(null);
// IE6~7 不支持,IE8 开始支持
// 3.withCredentials 属性
// 指定使用 Ajax 发送请求时是否携带 Cookie
// 使用 Ajax 发送请求,默认情况下,同域时,会携带 Cookie;跨域时,不会
// xhr.withCredentials = true;
// 最终能否成功跨域携带 Cookie,还要看服务器同不同意
// const url = 'https://www.imooc.com/api/http/search/suggest?words=js';
// // const url = './index.html';
// const xhr = new XMLHttpRequest();
// xhr.onreadystatechange = () => {
// if (xhr.readyState != 4) return;
// if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304) {
// console.log(xhr.response);
// }
// };
// xhr.open('GET', url, true);
// xhr.withCredentials = true;
// xhr.send(null);
// IE6~9 不支持,IE10 开始支持
// XHR 的方法
// <!-- <form
// action="https://www.imooc.com/api/http/search/suggest?words=js"
// method="post"
// >
// <input type="text" name="username" />
// <input type="password" name="password" />
// <input type="submit" value="提交" />
// </form> -->
// <script>
// 1.abort()
// 终止当前请求
// 一般配合 abort 事件一起使用
// const url = 'https://www.imooc.com/api/http/search/suggest?words=js';
// const xhr = new XMLHttpRequest();
// xhr.onreadystatechange = () => {
// if (xhr.readyState != 4) return;
// if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304) {
// console.log(xhr.response);
// }
// };
// xhr.open('GET', url, true);
// xhr.send(null);
// xhr.abort();
// 2.setRequestHeader()
// 可以设置请求头信息
// xhr.setRequestHeader(头部字段的名称, 头部字段的值);
// const url = 'https://www.imooc.com/api/http/search/suggest?words=js';
// const url = 'https://www.imooc.com/api/http/json/search/suggest?words=js';
// const xhr = new XMLHttpRequest();
// xhr.onreadystatechange = () => {
// if (xhr.readyState != 4) return;
// if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304) {
// console.log(xhr.response);
// }
// };
// xhr.open('POST', url, true);
// 请求头中的 Content-Type 字段用来告诉服务器,浏览器发送的数据是什么格式的
// xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
// xhr.setRequestHeader('Content-Type', 'application/json');
// xhr.send(null);
// xhr.send('username=alex&age=18');
// xhr.send(
// JSON.stringify({
// username: 'alex'
// })
// );
//
// XHR 的事件
// 1.load 事件
// 响应数据可用时触发
// const url = 'https://www.imooc.com/api/http/search/suggest?words=js';
// const xhr = new XMLHttpRequest();
// // xhr.onload = () => {
// // if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304) {
// // console.log(xhr.response);
// // }
// // };
// xhr.addEventListener(
// 'load',
// () => {
// if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304) {
// console.log(xhr.response);
// }
// },
// false
// );
// xhr.open('GET', url, true);
// xhr.send(null);
// IE6~8 不支持 load 事件
// 2.error 事件
// 请求发生错误时触发
// const url = 'https://www.imooc.com/api/http/search/suggest?words=js';
// const url = 'https://www.iimooc.com/api/http/search/suggest?words=js';
// const xhr = new XMLHttpRequest();
// xhr.addEventListener(
// 'load',
// () => {
// if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304) {
// console.log(xhr.response);
// }
// },
// false
// );
// xhr.addEventListener(
// 'error',
// () => {
// console.log('error');
// },
// false
// );
// xhr.open('GET', url, true);
// xhr.send(null);
// IE10 开始支持
// 3.abort 事件
// 调用 abort() 终止请求时触发
// const url = 'https://www.imooc.com/api/http/search/suggest?words=js';
// const xhr = new XMLHttpRequest();
// xhr.addEventListener(
// 'load',
// () => {
// if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304) {
// console.log(xhr.response);
// }
// },
// false
// );
// xhr.addEventListener(
// 'abort',
// () => {
// console.log('abort');
// },
// false
// );
// xhr.open('GET', url, true);
// xhr.send(null);
// xhr.abort();
// IE10 开始支持
// 4.timeout 事件
// 请求超时后触发
// const url = 'https://www.imooc.com/api/http/search/suggest?words=js';
// const xhr = new XMLHttpRequest();
// xhr.addEventListener(
// 'load',
// () => {
// if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304) {
// console.log(xhr.response);
// }
// },
// false
// );
// xhr.addEventListener(
// 'timeout',
// () => {
// console.log('timeout');
// },
// false
// );
// xhr.open('GET', url, true);
// xhr.timeout = 10;
// xhr.send(null);
// IE8 开始支持
</script>
</body>
</html>
ES6新增方法和属性以及ajax笔记
最新推荐文章于 2024-08-14 11:59:39 发布