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 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
ES6允许使用箭头(=>) 定义函数,箭头函数提供了一种更加简洁的函数书写方式,箭头函数多用于匿名函数的定义
箭头函数的注意点
//箭头函数
//箭头函数的结构: const/Let 函数名=参数=>函数体
const add = (x, y) => {
return X + y;
};
console.log(add(1,2));//3
//将一般函数改写成箭头函数
function add() {}; //声明形式
const add = function() {}; //函数表达式形式
const add = () => {}; //箭头函数的形式
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
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
解构赋值:解析某一数据的结构,将我们想要的东西提取出来赋值给变量
数组解构赋值的原理:模式(解构)匹配,索引值相同的完成赋值
//模式匹配 索引值完成赋值
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
默认值的基本用法
常见的类数组解构赋值
//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]
//对象的展开
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
//数组:数组是一系列有序的数据集合
//Set:是一系列无序,没有重复值的数据集合
const s = new Set();
s.add(1);
s.add(2);
//set中不能允许有重复的值
console.log(s);
//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
1
2
3
//数组去重
console.log([...new Set([1,2,3,1])]);//[1,2,3]
//字符串去重
console.log([...new Set('aabcd')]).join(' ');//bcd
//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
add() set()/get()
has() has()
delete() /clear() delete() /clear()
forEach() forEach()
size属性 size属性
Set/Map构造函数的参数
//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());
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
}
includes()判断字符串中是否包含某些字符
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
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
}))
应用场景
//应用场景
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,……)用来合并对象,返回的是目标对象
同名属性的替换:后面的属性会替换掉前面的属性
基本数据类型作为源对象 ,与对象的展开相似 先转换成对象再合并
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():获取对象的键值
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()等方法是构造方法 返回的是数组
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);
catch专门用来处理失败状态
catch()可以捕获它前面的错误
一般建议,Promise对象后面要跟catch方法这样可以处理Promise后面发生的错误
//什么时候执行
//当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对象的状态变化
传入多个Promise实例,包装成一个新的Promise实例返回值
promise.all()的状态变化与所有传入的Promise实例对象状态有关
所有状态变成resolved 最终的状态才会变成resolved
只要有一个状态变成rejected最终的状态才会变成rejected
Promise.race()的状态取决于第一个完成Promise实例的对象
如果第一个完成的成功了,那最终的就成功了,如果第一个完成的失败了 那最终的就失败了
export default 导出和对应的 import 导入
export 导出和对应的 import 导入
//module.js
const age = 20;
export default age;
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'
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构造函数继承
// 手机
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();
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 函数的返回值为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 必须写在 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请求
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();