一、let关键字
let关键字用来声明变量,使用let声明的变量有几个特点:
- 不允许重复声明
- 有块级作用域
- 不存在变量提升
- 不影响作用域链
let关键字代码说明
//let不允许重复声明
let a=2;
let a=3;
console.log(a);
//报错:uncaught SyntaxError:Identefter 'a'has already been declared
//let不允许重复声明
function func(a){
let a=9;
}
func();//报错:uncaught SyntaxError:Identefter 'a'has already been declared
//var会提升变量的声明到当前作用域的顶部
console.log(a);//undefined
var a=10;
//let const不存在变量的提升
console.log(b); // Cannot access'b' before initialization
let b = 10;
//暂时性死区:只要作用城内存在let const
//他们所声明的变量或者常量就自动绑定这个区域,不再受到外部作用域的影响
let a = 2;
function func() {
console.log(a); //Cannot access 'a' before initialization
let a = 1;
}
func();
//暂时性死区:只要作用城内存在let const
//他们所声明的变量或者常量就自动绑定这个区域,不再受到外部作用域的影响
let b = 1;
function fun() {
console.log(a); //Cannot access 'a' before initialization
}
fun();
//window对象的属性和方法
//全局作用域中,var声明的变量,通过function声明的函数,会自动变成window对象的属性和方法
//let const 不会
//var function
var age= 19;
function add() {}
console. log(window.age);// 19
console.log(window.add === add); //true
//块级作用域:var没有块级作用域
for (vari=0;i<3;i++) {
//console. log(i);//012
}
console.log(i);//3
//let const有块级作用域
for(leti=0;i<3;i++) {
//console.Log(i);//012
}
console.log(i);// Uncaught ReferenceError: i is not defined
二、const关键字
const关键字用来声明常量,const声明有以下特点:
- 声明必须赋初始值
- 标识符一般为大写(习惯)
- 不允许重复声明
- 值不允许修改
- 有块级作用域
const关键字代码说明
//const声明常量
const dog = '旺财' ;
console.log(dog); //旺财
//不允许重复声明
const a = 1;
const a = 3;
console.log(a);//SyntaxError: Identifier 'a' has already been declared
//不允许重复声明注意:对数组元素的修改和对对象内部的修改是可以的(数组和对象存的是引用地址
//基本数据类型
const sex='male';
sex = 'female';
console.log(sex);//Assignment to constant variable.
//引用数据类型
const person ={
username: 'Cai'
}
person.username ='Zhangsan',
console.log(person);
三、模板字符串
模板宇符串(template string)是增强版的宇符串,用反引号(`)标识
模板宇符串特点:
•字符串中可以出现换行符;
•可以使用 $(xxx}形式引用变量
•对于模板字符串 所有的空格 换行 缩进都会被保留在输出之中 怎么写就怎么输出
//一般字符串:"Cai" 'Lily'
//模板字符串:`Cai`
const username1 = "Cai";
const username2 = `Cai`;
console.log(username1, username2); //Cai Cai
console.log(username1 === username2) //true
//模板字符串与一般字符串的区别
//和其他东西一起注入的时候,使用模板字符串方便注入
const person = {
name:'Cai',
age: 19,
sex:'Female'
}
//一般字符串的做法
const info = '我叫' + person.name',我今年' + person.age +'岁了,' +'我的性别是'+person.sex;
console.log(info);//我叫Cai,我今年19岁了,我的性别是Female
//模板字符串与一般字符串的区别
//和其他东西一起注入的时候,使用模板字符串方便注入
const person = {
name:'Cai',
age: 19
sex: 'Female'
//模板字符串的做法
const info =`我叫${person.name},年龄${person.age},性别${person.sex},`;
console.log(info);//我叫Cai,年龄19,性别Female
//输出多行字符
//一般的字符串
const info ='第一行\n第二行';
console.log(info);
//对于模板字符串所有的空格 换行缩进都会被保留在输出之中怎么写就怎么输出
const info1 =`第一行
第二行`;
console.log(info1);
//输出`和\等特殊字符
// const info = `\``;
// console.log(info); //`
// const info = `\\`;
// console.log(info); //\
只要最后可以得出一个值的会可以通过${}注入到模板字符串中;看下面代码解说
const username = 'Cai';
const person = {
age: 19,
sex: 'Female'
}
const getSex = function(sex) {
return sex === 'Female' ? 'Female' : 'Male'
}
//只要最终可以得出一个值的就可以通过${}注入到模板字符串中
const result = `${username},${person.age-1},${getSex(person.sex)}`;
console.log(result); //Cai,18,Female
四、模板字符串练习案例
<script>
const students = [{
username: 'Cai',
age: 18,
sex: 'male'
}, {
username: 'zhangsan',
age: 30,
sex: 'male'
}, {
username: 'lisi',
age: 13,
sex: 'male'
}]
const list = document.getElementById("list");
let html = '';
for (let i = 0; i < students.length; i++) {
html += `<li>我的名字是${students[i].username},我的年龄是${students[i].age},我的性别是${students[i].sex}</li>`;
}
list.innerHTML = html;
</script>
五、箭头函数
ES6允许使用箭头(=>) 定义函数,箭头函数提供了一种更加简洁的函数书写方式,箭头函数多用于匿名函数的定义
箭头函数的注意点
- 如果形参只有一个,则小括号可以省略
- 函数体如果只有一条语句,则花括号可以省略,并省略return,西数的返回值为该条语句的执行结果
- 箭头函数 this 指向声明时所在作用域下 this 的值
- 箭头函数不能作为构造函数实例化
- 不能使用 arguments
//箭头函数
//箭头函数的结构: const/Let 函数名=参数=>函数体
const add = (x, y) => {
return X + y;
};
console.log(add(1,2));//3
//将一般函数改写成箭头函数
function add() {}; //声明形式
const add = function() {}; //函数表达式形式
const add = () => {}; //箭头函数的形式
<script>
//箭头函数
//箭头函数的结构:const/let 函数名= 参数=>函数体
const add = (x, y) => {
return x + y;
};
console.log(add(1, 2)); //3
//将一般函数改写成箭头函数
function add() {}; //声明形式
const add = function() {}; //函数表达式形式
const add = () => {}; //箭头函数的形式
</script>
箭头函数的注意事项
1、单个参数可以省略圆括号
//单个参数可以省略圆括号
const add = x => {
return x + 1
};
console.log(add(1)); //2
2、无参数或多个参数不可以省略圆括号
//无参数或多个参数不可以省略圆括号
const add = () => {
return 1 + 1
}
console.log(add()); //2
3、当行函数体可以省略{}和return
//单行函数体:可以同时省略{}和return
const add = (x, y) => x + y;
console.log(add(1, 2)); //3
//如果箭头函数返回单行对象 可以在{}外面加上()让浏览器不再认为那是函数体的花括号
const add = (x, y) => ({
value: x + y
})
console.log(add(1, 1));
六、非箭头函数中的this指向问题
- 全局作用域中的this指向window
- 函数中的this,只有函数被调用时,才有明确的指向
- this指向调用其所在函数的那个对象
- 没有具体调用对象,this指向undefined,在非严格模式下指向window
<script>
//全局作用域中的this指向
// console.log(this); //window
//一般函数(非箭头函数)中的this指向问题
// 'use strict';
function add() {
console.log(this);
//严格模式下this指向undefined
//undefined ->window(非严格模式下转化为window)
}
add();
//构造函数中的this指向
function Person(username, password) {
this.username = username;
this.password = password;
console.log(this); //构造函数中的this指向构造函数实例化后生成的对象
}
var p = new Person('Cai', 12);
</script>
七、箭头中的this指向问题
- 箭头函数没有自己的this
- 箭头函数中的this是通过作用域链查找的
//箭头函数中的this指向问题
//箭头函数没有自己的this
const calc = {
add: () => {
console.log(this);
}
}
calc.add(); //window
//练习
const calc = {
add: function() {
const adder = () => {
console.log(this);
}
adder();
}
}
calc.add();//calc
//练习
const calc = {
add: function() {
const adder = () => {
console.log(this);
}
adder();
}
}
const addFn = calc.add;
addFn(); //undefined->window
不适合箭头函数的场景
- 作为构造函数
- 需要this指向调用对象的时候
- 需要使用arguments的时候
八、解构赋值
解构赋值:解析某一数据的结构,将我们想要的东西提取出来赋值给变量
数组解构赋值的原理
数组解构赋值的原理:模式(解构)匹配,索引值相同的完成赋值
//模式匹配 索引值完成赋值
const [a, b, c] = [1, 2, 3];
console.log(a, b, c);
//不取的直接用逗号跳过
const [a, [b, , ], e] = [1, [2, 4, 5], 3];
console.log(a, b, e); //1 2 3
数组解构赋值的默认值
默认值的基本用法
<script>
// 默认值的基本用法
// const [a, b] = [];
// const [a, b] = [undefined, undefined];
// const [a = 1, b = 2] = [];
// console.log(a, b); //1 2
//默认值的生效条件
//只有当一个数组成员严格等于undefined时对应的默认值才会生效
// const [a = 1, b = 2] = [3, 0];
// console.log(a, b); //3 0
// const [a = 1, b = 2] = [3, null];
// console.log(a, b); // 3 null
// const [a = 1, b = 2] = [3];
// console.log(a, b); //3 2
//默认值表达式 默认值表达式是惰性求值的
// const func = () => {
// console.log('我被执行了');
// return 2;
// }
// const [x = func()] = [1];
// console.log(x); //1
const func = () => {
console.log('我被执行了');
return 2;
}
const [x = func()] = [];
console.log(x); // 我被执行了 2
</script>
常见的类数组解构赋值
//arguments
function func() {
const [a, b] = arguments;
console.log(a, b); //1 2
}
func(1, 2)
//NodeList
const [p1, p2, p3] = document.querySelectorAll('p');
console.log(p1, p2, p3);
//函数参数的结构赋值
const array = [1, 2];
const add = ([x, y]) => x + y;
console.log(add(array)); //3
//交换变量的值
let x = 1;
let y = 2;
[x, y] = [y, x];
console.log(x, y); //2 1
对象的解构赋值
//模式匹配,属性名相同的完成赋值
const {
age,
username,
password
} = {
age: 18,
username: 'Cai',
password: 123
}
console.log(age, username, password); //18 'Cai' 123
//取别名
const {
age: age,
username: uname
} = {
age: 19,
username: 'Li'
}
console.log(age, uname); //19 'Li'
//对象的属性值严格等于undefined时对应的值才会生效
const {
username = 'Zhang', age = 0
} = {
username: 'alex'
}
console.log(username, age); //alex 0
//如果将一个已经声明的变量用于对象的解构赋值
//整个赋值需要在圆括号中进行
let x = 2;
({
x
} = {
x: 1
})
console.log(x); //1
//函数参数的解构赋值
const Person = ({
age,
username
}) => console.log(username, age); //
Person({
age: 19,
username: 'Cai'
})
//复杂的嵌套
const obj = {
x: 1,
y: [1, 2, 3],
z: {
a: 5,
b: 6
}
};
const {
y,
y: [, , ss],
z
} = obj;
console.log(ss, y, z);
字符串的解构赋值
//字符串的解构赋值
//按照数组的形式
const [a, b, , , e] = 'hello';
console.log(a, b, e); // h e o
//字符串的解构赋值
//按照对象的形式
const {
0: a,
1: b
} = 'hello'
console.log(a, b); // h e
九、对象字面量的增强与函数参数的默认值
//对象字面量
//实例化构造函数生成对象
const person = new Object();
person.age = 18;
person.speak = function() {};
//对象字面量
const person = {
age: 18,
speak: function() {}
}
属性的简洁表示法:键名和变量名或者常量名一样的时候,可以只写一个
//属性的简洁表示法:键名和变量或者常量名一样的时候,可以只写一个
const age = 19;
const person = {
// 'age': age
age
};
console.log(person);
方法的简洁表示法:可以省略冒号和function关键字
//方法的简洁表示法
//方法可以省略冒号和function关键字
const person = {
// speak: function() {}
speak() {
}
}
console.log(person);
方括号语法
//方括号语法和点语法
const prop = 'age';
const person = {
[prop]: 19
};
console.log(person);
函数参数的默认值
调用函数的时候传参了,就用传递的参数,如果没传就用默认值
const multiple = (x, y) => {
if (typeof y === 'undefined') {
y = 1;
}
return x * y;
}
console.log(multiple(2, 2)); //4
函数参数默认值的注意事项
//默认值的生效条件
// 不传递参数或者明确的传递undefined参数 只有这两种情况下 默认值才会生效
const multiply = (x, y = 1) => x * y
console.log(multiply(2, 0)); //0
console.log(multiply(2, null)); //0
console.log(multiply(2, undefined)); //2
//函数参数的默认值 最好从列表的右边开始
// const multiply = (x = 1, y) => x * y;
// console.log(multiply(undefined, 2)); //2
const multiply = (x, y = 1) => x * y;
console.log(multiply(2)); //2
十、剩余参数
剩余参数:剩余参数永远只是个空数组,即使没有值也是空数组
// 认识剩余参数
//剩余参数永远是个数组 即使没有值 也是空数组
const add = (x, y, z, ...args) => {
console.log(x, y, z, args);
}
add(1, 2, 3, 4, 5)
剩余参数的注意事项
//箭头函数的剩余参数
// 箭头函数的参数部分即使只有一个剩余参数也不能省略圆括号
const add = (...args) => {
}
//使用剩余参数替代arguments获取实际参数
// const add = function() {
// console.log(argments);
// }
//
const add = (...args) => {
console.log(args); //[1, 2]
}
add(1, 2)
//剩余参数的位置
//剩余参数只能是最后一个参数 之后不能再有其他参数 否则会报错
const add = (x, y, ...args) => {
console.log(x, y, args);
}
add(1, 2, 3, 4, 5, 6)
剩余参数的应用
// 剩余参数与解构赋值结合使用
// const [a, ...args] = [1, 2, 3, 4, 5];
// console.log(a, args);
const func = ([num, ...args]) => {}
func([1, 2, 3, 4])
const {
x,
y,
...z
} = {
x: 1,
b: 2,
y: 3,
d: 4
}
console.log(x, y, z);
十一、展开运算符
//数组展开运算符的基本用法
console.log(Math.min(...[2, 33, 44])); //2
//相当于
console.log(Math.min(3, 33, 22)); //3
区分剩余参数和展开运算符
//区分剩余参数和展开运算符
//剩余参数 2,3,4->:[2,3,4]
//展开运算符: [2,3,4]->2,3,4
const add = (...args) => {
console.log(args);
}
add(1, 2, 3, 4) //[1,2,3,4]
const add = (...args) => {
// console.log(args);
console.log(...args);
}
add(1, 2, 3, 4) //1 2 3 4
console.log([
...[1, 2, 3], 4, 5
]); //[1, 2, 3, 4, 5]
数组展开运算符的应用
<script>
// 复制数组
const arr1 = [3, 4, 5, 6];
const arr2 = [...arr1]
console.log(arr2); // [3, 4, 5, 6]
//合并数组
const arr3 = [1, 2, 3];
const arr4 = [4, 5, 6]
console.log([99, 98, ...arr3, ...arr4, 100]); //[99, 98, 1, 2, 3, 4, 5, 6, 100]
//字符串转为数组
console.log(...
'Cai') //C a i
console.log([...
'Cai'
]) //['C', 'a', 'i']
</script>
对象的展开
//对象的展开
const apple = {
color: 'red',
taste: 'nice'
}
console.log({...apple
});
console.log({...apple
} === apple); //false
//合并对象
// 新对象拥有全部的属性 相同的属性 后者覆盖前者
const apple = {
color: '红色',
shape: '球形',
taste: '甜'
}
const pen = {
color: '黑色',
shape: '长方形',
use: '写字'
}
console.log({...apple,
...pen
});
// 对象中属性的展开
// 不对展开对象中的对象属性
const app = {
features: {
taste: '甜'
}
}
const pen = {
features: {
color: '黑色',
shape: '圆柱形'
},
use: '写字'
}
console.log({...app,
...pen
})
十二、Set和Map数据结构
//Set
//数组:数组是一系列有序的数据集合
//Set:是一系列无序,没有重复值的数据集合
const s = new Set();
s.add(1);
s.add(2);
//set中不能允许有重复的值
console.log(s);
//set没有下标去标识每一个值,所以set是无序的也不能像数组那样通过下标去访问set的成员
set实例的属性和方法
// set实例的属性和方法
//add方法添加成员
const s = new Set();
s.add(1).add(2).add(3);
console.log(s);
//has方法 判断是否有成员
console.log(s.has(1)); //true
console.log(s.has(100)); //false
//delete删除
s.delete(1);
//使用delete删除不存在的成员,什么都不会发生,也不会报错
s.delete(9);
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(s)
//size属性
console.log(s.size) //2
set构造函数的参数
- 数组
- 字符串、arguments、NodeList、Set等
<body>
<p>1</p>
<p>2</p>
<p>3</p>
<script>
//数组
const s = new Set([1, 2, 3, 4, 5])
console.log(s);
//字符串
console.log(new Set('hello'));
//arguments
function func() {
console.log(new Set(arguments));
}
func(1, 2, 3)
//nodeList
console.log(new Set(document.querySelectorAll('p')));
</script>
</body>
Set的注意事项
<script>
//判断重复的方式
const s = new Set([1, 2, 3, 1]);
console.log(s); //{ 1,2,3}
//Set对重复的判断结伴遵循严格相等的原则(===)
//但是对于NaN的判断与===不同,Set中的NaN等于NaN
console.log(1 === 1); //true
console.log(NaN === NaN); //false
const s1 = new Set([NaN, 1, 3, NaN]);
console.log(s1); // {NaN, 1, 3}
</script>
什么时候用Set?
- 数组或字符串去重时
- 不需要通过下标访问的时候,只需要遍历时
- 为了使用Set提供的方法和属性的时候(add、delete、clear、has、forEach、size等)
Set的应用
//数组去重
console.log([...new Set([1,2,3,1])]);//[1,2,3]
//字符串去重
console.log([...new Set('aabcd')]).join(' ');//bcd
十三、Map
<script>
//Map和对象都是键值对的集合
//对象
const person = {
name: 'Cai',
age: 18
}
//Map
const m = new Map();
console.log(m);
m.set('age', 19);
m.set('name', 'Zhan')
console.log(m);
// Map和对象的区别
//对象一般用字符串当做键
// 基本数据类型:数字、字符、undefined、布尔值、null
//引用数据类型:对象([],{},函数,Set,Map()等)
//以上的都可以作为map的键
const l = new Map();
m.set('name', 'Zhangx');
m.set('age', 20);
m.set(true, 'true');
m.set(undefined, 'undefined');
</script>
<script>
const m=new Map();
//使用set添加新成员,键如果已经存在,后面添加的键值对覆盖已有的
m.set('age',18).set(true,'true').set('age',22);
console.log(m);
</script>
<script>
//set方法
const m = new Map();
//使用set添加新成员,键如果已经存在,后面添加的键值对覆盖已有的
m.set('age', 18).set(true, 'true').set('age', 22)
console.log(m);
//get
console.log(m);
console.log(m.get('age')); //22
console.log(m.get(true)); //true
//get获取到不存在的成员 返回undefined
console.log(m.get('name')); //undefined
//has
console.log(m.has('age')) //true
//使用delete删除不存在的成员什么都不发生也不报错
m.delete('name');
//clear一键删除
// m.clear();
// console.log(m)
//forEach
m.forEach(function(value, key, map) {
console.log(value, key, map)
console.log(this); //#document
}, document)
// 属性size
console.log(m.size) //2
</script>
Map构造函数的参数
<script>
//只能传二维数组 而且必须体现出键值
console.log(new Map([
['name', 'Cai'],
['age', 18],
]));
//SetMap
const s = new Set([
['name', 'Li'],
['age',100]
]);
console.log(new Map(s));
console.log(s);
//Map 复制一个新的Map
const s2 = newMap([
['name', 'LL'],
['sex', 'male ']
]);
console.log(s2);
const s3 = new Map(s2);
console.log(s3);
console.log(s2 === s3); //false
</script>
Map中的注意事项
//Map中NaN等于NaN
const s4 = new Map();
s4.set(NaN, 1).set(NaN, 2);
console.log(s4);
//什么时候使用Map
//如果只是需要key-value的结构,或者需要字符串以外的值做键
// 只有模拟现实世界的实体时,才使用对象
const person = {};
Set和Map总结
Set/Map实例的方法与属性
Set Map
add() set()/get()
has() has()
delete() /clear() delete() /clear()
forEach() forEach()
size属性 size属性
Set/Map构造函数的参数
- Set:数组、字符串、arguments、NodeList、 Set等
- Map:数组(二维数组)、Set、Map等
- 基本可用严格相等(===)判断
- 例外:对于 NaN 的判断与===不同, Set/Map中NaN等 于NaN
十四、遍历器for...of
//Iterator的作用
//遍历器(迭代器)用来遍历的
//使用
const it = [1, 2][Symbol.iterator]();
console.log(it.next()); //{value: 1, done: false}
console.log(it.next()); //{value: 1, done: false}
console.log(it.next()); //{value: undefined, done: true}
//it可遍历对象(可迭代器)
//Symbol.iterator:可遍历对象的生成方法
//什么是iterator?
//Symbol.iterator(可遍历对象生成的方法)->it(可遍历对象)->it.next()->...(直到done为true)
const it = [1, 2, 3][Symbol.iterator]();
console.log(it.next());
console.log(it.next());
console.log(it.next());
console.log(it.next());
for...of
const it = [1, 2, 3];
for (const item of it) {
console.log(item); // 1 2 3
}
// const it = [1, 2, 3];
// for (const item of it){
// console.Log(item);//1 2
//
const it = [1, 2, 3, 45];
for (const item of it)
{
console.log(item);
}
//在for of 中取得数组的索引值
const arr1=[1, 2, 3]
//keys()得到的是索引的可遍历对象 可以遍历出索引值
for (const key of arr1.keys()){
console.log(key);//0 1 2
}
//values()得到的是指的可遍历对象 可以遍历出值
for (const value of arr1.values ())
{
console.log(value);//1 2 3
}
//entries() 得到的是索引+值组成的数组的可遍历对象
for (const entries of arr1.entries())
{
console.log(entries);//[8, 1] [1, 2][2,3]
}
//或者
for (const [index, value] of arr1.entries())
{
console.log(index, value);//0 1 1 2 2 3
}
什么是原生可遍历?
- 只要有Symbol.iterator方法并且这个方法可以生成可遍历对象就是可遍历的
- 只要可遍历就可以使用for of循环来统一遍历
原生可遍历有哪些?
- 数组、字符串、Set、Map、arguments、NodeList
非原生可遍历有哪些?
- 一般的对象
十五、ES6新增的方法
字符串中新增的方法
includes()判断字符串中是否包含某些字符
<script>
//includes()判断字符串中是否包含某些字符
console.log('abc'.includes('a')); //true
console.log('abcd'.includes('abc')); //true
console.log('abcs'.includes('f')); //false
//第二个参数
//表示开始搜索的位置默认是0
console.log('abc'.includes('a', 0)); //true
console.log('abc'.includes('a', 1)); //false
//在实际开发中的应用
//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')
url = addURLParam(url, 'sort', 'pop')
console.log(url);
</script>
padStart()和padEnd
padStart()用于头部补全,padEnd()用于尾部补全。
参数(接收两个参数):
第一个参数,当字符串需要填充到的目标长度。如果这个值小于当前字符串的长度,则返回当前字符串本身。
第二个参数,用于补充的字符串,如果字符串长度过长,则会删除后面的多出的字符串,进行补全。
//补全字符串的长度
console.log('a'.padStart(5, 'ba')); //babaa
console.log('x'.padEnd(4,'d')); //xddd
//注意事项:当元字符串的长度, 等于或大于最大长度, 不会消减原来的字符串
//字符串补全不生效返回原来的字符串
console.log('xxx' .padStart(2,'ab'))//xxx
console.log('xxx'.padEnd(2, 'ab'))//xxx
//用来补全的字符串与原字符串长度之 和超过了最大的长度
//截出超出位数的补全字符串, 原字符串不动
console.log('xxx' .padStart(10, '0123456789')); //0123456xxx
console.log('xxx'.padEnd(10, '0123456789')); //xxx0123456
//如果省略第二个参数, 默认使用空格来填充
console.log('x'.padStart(4));// x
console.log('x'.padEnd(4));//x
//在实际开发中的应用
//显示日期格式
//2020-10-10
//2020-1-2
console.log('10' .padStart(2, 0));
console.log('1' .padStart(2, 0));
适用场景:
//在实际开发中的应用
//显示日期格式
//2020-10-10
//2020-1-2
console.log('10'.padStart(2, 0));//10
console.log('1'.padStart(2, 0));//01
trimStart()、trimEnd()、trimLeft()、trimRight()、trim()
<script>
//清除字符串的首或尾空格 中间的不会清除
const S = a C
console.log(s.trimStart());//头部
console.log(s.trimEnd ());//尾部
console.log(s.trimLeft ());//左边
console.log(s.trimRight(); //右边
console.log(s.trim ());//左右(头尾) 两边部分
</script>
数组中新增的方法
<script>
//includes() 判断数组中是否包含某个成员
console.log([1, 2, 3].includes('2')); //false
console.1og([1, 2, 3].includes(2)); //true //第二个参数表示搜索的起始位置默认值是0
console.1og([1, 2, 3].includes(2, 1));//true console.1og([1, 2, 3].includes(2, 3));//faLse
//基本遵循严格相等(===) 但是对于NaN的判断与===不同
//includes认为NaN===NaN
console.log(NaN === NaN); //faLse
console.log([1, 2, NaN].includes( NaN)); //true
//在实际中的应用
//数组去重[1,2,3,1]
const arr =[];
for (const item of[1, 2, 3, 2, 1]){
if(!arr.includes(item)){ arr.push(item);
}
}
console.log(arr)//[1,2,3]
</script>
find()和findIndex()函数详解
find()函数用来查找目标元素(查找符合条件的第一个元素),它的参数是一个回调函数。在回调函数中可以写你要查找元素的条件,当条件成立为true时,返回该元素。如果没有符合条件的元素,返回值为undefined。回调函数有三个参数。value:当前的数组元素。index:当前索引值。arr:数组本身
//find(): 找到满足条件的一个立即返回
console.log([10, 20, 30, 50, 100].find((value, index, arr) => {
return value > 10; //20
}))
findIndex()函数返回符合条件的值的位置(索引),找不到就返回-1。
//findIndex():找到满足条件的一个,立即返回索引
console.log([10, 20, 30, 50, 100].findIndex((value, index, arr) => {
return value > 10; //1
}))
<script>
/find():找到满足条件的一个立即返回
//findIndex(): 找到满足条件的一个,立即返回索引
[10, 20, 30, 50, 100].find((value, index, arr) =>{
console.log(value, index, arr)
})
//find():找到满足条件的一个立即返回
console.log([10, 20, 30, 50, 100].find((value,index,arr) =>{
return value > 10; //20
}))
//findIndex():找到满足条件的一个, 立即返回索引
console.log([18, 20, 30, 50, 100].findIndex((value, index, arr) => {
return value >10;//1
}))
</script>
应用场景
//应用场景
const student : =[{
name: 'Cai'
sex: 女,
age: 19
},{
name: 'Lily'
age: 20,
sex:
},{
name: 'LL'
age: 22,
sex: '男'
}];
console.log(student.find(value =>
value.sex === '女'
))
console.log(student.findIndex(vaLue =>
value.sex === 女'
))
对象的新增方法和属性
Object.assign(目标对象,源对象1,源对象2,……)用来合并对象,返回的是目标对象
-
同名属性的替换:后面的属性会替换掉前面的属性
-
基本数据类型作为源对象 ,与对象的展开相似 先转换成对象再合并
<script>
//Object.assign()用来合并对象
const apple = {
color: '红色',
shape: '圆形',
taste:'甜'
}
const pen = {
color: '黑色',
shape: 圆柱形·
use: '写字'
}
//0bject.assign() 直接合并到了第一个参数中, 返回的就是合并之后的对象
console. log(Object.assign(apple, pen));
console.log(apple === 0bject.assign(apple,pen)); //true
//可以合并多个对象
console.1og(Object.assign({}, apple, pen))
//返回结果: 新的对象
</script>
const apple1 = {
color: ['红色', '蓝色'],
shape: '圆形',
taste: '甜'
}
const pen1 = {
color: ['黑色', '金色'],
shape: '圆柱形',
use: '写字'
}
console.log(Object.assign({}, apple1, pen1))
应用场景:合并默认参数和默认参数
//合并默认参数和默认参数
const logUser = userOptions => {
const Default = {
username: 'Zhangsan',
age: 0,
sex: 'male'
}
const options = Object.assign({},
Default, userOptions);
console.log(options);
}
//logUser();
logUser({
username: 'Cai'
})
Object.keys()、Object.values()、Object.entries()
-
Object.keys():获取对象中的键
-
Object.values():获取对象中的值
-
Object.entries():获取对象的键值
const person =
name: 'Cai',
age: 9,
hobby: 'play'
}
console.log(Object.keys(person))
console.log(Object.values(person));
console.log(Object.entries person));
对象的Object.keys()、Object.values()、Object.entries()与数组的keys()、values()、entries()的方法的区别
-
数组的keys()、values()、entries()的方法是实例方法,返回的都是Iterator
-
对象的Object.keys()、Object.values()、Object.entries()等方法是构造方法 返回的是数组
<script>
const person = {
name: 'Cai',
age: 9,
hobby: 'play'
}
console.log(Object.keys(person))
console.log(Object.values(person));
console.log(Object.entries(person));
//与数组类似方法的区别
//数组的keys()、values()、entries()的方法是实例方法,返回的都是Iterator
//对象的Object.keys()、Object.values()、Object.entries()等方法是构造方法 返回的是数组
console.log([1, 2, 3].keys());
console.log([1, 2, 3].values());
console.log([1, 2, 3].entries());
</script>
十六、Promise
Promise的基本用法
const p = new Promise((resolve, reject) => {
//Promise有三种状态,一是开始pending(未完成)
//执行 resolve变成fulfilled( resolved)已成功
//执行reject变成reject 已失败
//Promise的状态一旦变化了 就不会再改变了
//pending=>fulfilled( resolved)已成功
resolve({
username: 'li'
});
//pending=>rejected已失败
// reject();
})
//then方法
p.then((data) => {
console.log('success', data);
}, () => {
console.log('error');
})
console.log(p);
then()方法
<script>
const p = new Promise((resolve, reject) => {
//resolve();
reject();
});
p.then(
() => {
console.log('success');
},
() => {
console.log('err');
return 123;
//在then的回调函数中,return后面的东西,会用Promise包装一下
//return undefined
//等价于
//return new Promise((resolve, reject) => {
//resolve(undefined);
//})
//默认返回的永远都是成功状态的Promise对象
//return new Promise((resolve, reject) => {
// reject('reason')
//});
}).then(
(data) => {
console.log('success2', data);
// return undefined;等价于
return new Promise((resolve, reject) => {
resolve(undefined);
})
},
() => {
console.log('err2');
}
).then(
(data) => {
console.log('success3', data);
}, (err) => {
console.log('err3', err);
})
//then什么时候执行
//pending->fulfilled时,执行then的第一个回调函数
//pending->resolved时,执行then的第二个回调函数
//执行后的返回的值: 返回一个新的Promise对象
</script>
catch()方法
-
catch专门用来处理失败状态
-
catch()可以捕获它前面的错误
-
一般建议,Promise对象后面要跟catch方法这样可以处理Promise后面发生的错误
finally()方法
//什么时候执行
//当Promise状态发生变化时,不论如何都会执行,不变化不执行
new Promise((resolve, reject) => {
// resolve(123);
reject('reason');
}).finally((data) => {
console.log(data);
}).catch((err) => {
})
//本质:finally本质上是then()的特例
//上面的代码等价于
new Promise((resolve, reject) => {
// resolve(123);
reject('reason');
})
.then((result) => {
return result;
}, err => {
return new Promise((resolve, reject) => {
reject(err);
})
}).catch((err) => {
console.log(err);
})
Promise.all()
-
Promise.all()关注多个Promise对象的状态变化
-
传入多个Promise实例,包装成一个新的Promise实例返回值
-
promise.all()的状态变化与所有传入的Promise实例对象状态有关
-
所有状态变成resolved 最终的状态才会变成resolved
-
只要有一个状态变成rejected最终的状态才会变成rejected
Promise.race()
-
Promise.race()的状态取决于第一个完成Promise实例的对象
-
如果第一个完成的成功了,那最终的就成功了,如果第一个完成的失败了 那最终的就失败了
<script>
//Promise.race()
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.race()的状态取决于第一个完成Promise实例的对象
//如果第一个完成的成功了,那最终的就成功了,如果第一个完成的失败了 那最终的就失败了
const racePromise = Promise.race([p1, p2])
racePromise.then(data => {
console.log(data);
}, err => {
console.log(err);
})
</script>
Promise.allSettled()
<script>
//Promise.race()
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.allSettled()的状态与传入的promise状态无关
//永远都是成功的状态
//它只会忠实的记录下各个Promise的表现
const allSettledPromise = Promise.allSettled([p1, p2])
allSettledPromise.then(data => {
console.log('succ', data);
})
</script>
十七、Module的两种导入和导出
export default 导出和对应的 import 导入
export 导出和对应的 import 导入
//module.js
const age = 20;
export default age;
<script type="module">
//一个模块没有导出,也可以将其导入
//被导入的代码都会执行一遍,也仅仅会执行一遍
//使用export default可以随便起名(有语义化)
//一个模块只能有一个export default
import age from './module.js'; console.log(age); //基本用法
</script>
export function fn() {}
export class className {}
export const age1 = 19
导入导出时起别名:
export {fu as func,className as Person,age} from './module2.js'
整体导入:会导入所有的输出,包括export default导出的
import * as obj from './module.js'
<script type="module">
import { age } from './module2.js';
console.log(age);
import { fn } from './module2.js';
import { className } from './module2.js';
console.log(className);
import { age1 } from './module2.js';
console.log(age);
</script>
十八、class类
ES6 提供了更接近传统语言的写法,引入了 Class(类)这个概念,作为对象的模板。通过 class 关键字,可以定义类。基本上,ES6 的 class 可以看作只是一个语法糖,它的绝大部分功能,ES5 都可以做到,新的 class 写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已;
内容:
class 声明类;
constructor 定义构造函数初始化;
extends 继承父类;
super 调用父级构造方法;
static 定义静态方法和属性;
父类方法可以重写;
// class静态成员
// ES5写法
// function Phone() {}
// Phone.name = "手机";
// Phone.change = function () {
// console.log("我可以改变世界!");
// }
// let nokia = new Phone();
// console.log(nokia.name); // undefined
// // nokia.change();
// // 报错:Uncaught TypeError: nokia.change is not a function
// Phone.prototype.color = "黑色";
// console.log(nokia.color); // 黑色
// console.log(Phone.name);
// Phone.change();
// 注意:实例对象和函数对象的属性是不相通的
// ES6写法
class Phone {
// 静态属性,只有类有,实例对象是没有的
static name = "手机";
static change() {
console.log("我可以改变世界!");
}
}
let nokia = new Phone();
console.log(nokia.name);
console.log(Phone.name);
Phone.change();
ES5构造函数实现继承
// ES5构造函数继承
// 手机
function Phone(brand, price) {
this.brand = brand;
this.price = price;
}
Phone.prototype.call = function () {
console.log("我可以打电话!");
}
// 智能手机
function SmartPhone(brand, price, color, size) {
Phone.call(this, brand, price);
this.color = color;
this.size = size;
}
// 设置子级构造函数的原型
SmartPhone.prototype = new Phone;
SmartPhone.prototype.constructor = SmartPhone;
// 声明子类的方法
SmartPhone.prototype.photo = function () {
console.log("我可以拍照!");
}
SmartPhone.prototype.game = function () {
console.log("我可以玩游戏!");
}
const chuizi = new SmartPhone("锤子", 2499, "黑色", "5.5inch");
console.log(chuizi);
chuizi.call();
chuizi.photo();
chuizi.game();
十九、ES6class类继承
class中的getter和setter设置
// class中的getter和setter设置
class Phone {
get price() { //当price这个属性被读取,会执行这个函数
console.log("价格属性被读取了!");
// 返回值
return 123;
}
set price(value) {//当price这个属性被修改,会执行这个函数
console.log("价格属性被修改了!");
}
}
// 实例化对象
let s = new Phone();
console.log(s.price); // 返回值
s.price = 2999;
二十、async 和 await
async 函数
-
async 函数的返回值为promise对象;
-
promise 对象的结果由async 函数执行的返回值决定
// async函数:异步函数
async function fn() {
// return 123; // 返回普通数据
// 若报错,则返回的Promise对象也是错误的
// throw new Error("出错啦!");
// 若返回的是Promise对象,那么返回的结果就是Promise对象的结果
return new Promise((resolve, reject) => {
// resolve("成功啦!");
reject("失败啦!");
})
}
const result = fn();
// console.log(result); // 返回的结果是一个Promise对象
// 调用then方法
result.then(value => {
console.log(value);
}, reason => {
console.warn(reason);
});
await 表达式
-
await 必须写在 async 函数中;
-
await 右侧的表达式一般为 promise 对象;
-
await 返回的是 promise 成功的值;
-
await 的 promise 失败了, 就会抛出异常, 需要通过 try…catch 捕获处理;
// async函数 + await表达式:异步函数
// 创建Prmise对象
const p = new Promise((resolve,reject)=>{
resolve("成功啦!");
})
async function fn(){
// await 返回的是 promise 成功的值
let result = await p;
console.log(result); // 成功啦!
}
fn();
async 和 await 结合发送ajax请求
// async 和 await 结合发送ajax请求
function sendAjax(url) {
return new Promise((resolve, reject) => {
// 1、创建对象
const x = new XMLHttpRequest();
// 2、初始化
x.open("GET", url);
// 3、发送
x.send();
// 4、事件绑定
x.onreadystatechange = function () {
if (x.readyState == 4) {
if (x.status >= 200 && x.status <= 299) {
// 成功
resolve(x.response);
} else {
// 失败
reject(x.status);
}
}
}
});
}
async function main() {
let result = await sendAjax("https://api.apiopen.top/getJoke");
console.log(result);
}
main();