模板字符串
var name = "lilei"
const str = `${name}:是小学生`;
let、const
var的问题
- 声明提前,打乱程序正常的执行顺序
- 没有块级作用域的概念
var t = 0;
function fun1() {
t += 2;
}
function fun2() {
t += 1;
}
fun1();
fun2();
console.info(t);
上面的例子,在fun1和fun2执行完成后,变成了3.这个结果是正常的。再往下看
var t = 0;
function fun1() {
t += 2;
// 这里加入了一个不会执行的代码段
if (false) {
var t = 999;
}
}
function fun2() {
t += 1;
}
fun1();
fun2();
console.info(t);
如上面所示,在fun1中加入了一个不会执行的代码,但是执行完以后,t变成了1。
fun1中就因为存在声明提升才会导致这样的结果.fun1中
function fun1() {
var t; // !! 注意这里
t += 2;
if (false) {
t = 999;
}
}
let本质
相当于匿名函数自调
(function() {
})();
let三个小脾气
- 因为不会声明提升,所以不能在声明前使用,所以有
临时死区 - 在相同作用域内,
禁止声明两个相同的变量 - 因为let底层相当于匿名函数自调,所以即使在全局创建的let变量,在
window中也找不到
箭头函数
const fun1 = () => {
console.info("log");
}
不能使用箭头函数的地方
构造函数不能用(因为this)对象的方法不能用(因为this)
var name = "123"
var obj = {
name: "345",
getName: function() {
console.info(this.name)
},
getName2: () => {
console.info(this.name)
}
}
obj.getName(); // 345
obj.getName2(); // 123
原型对象方法不能用(因为this)DOM中事件处理函数不能用(因为this)- 箭头函数无法用
call,apply,bind改变this - 箭头函数不支持
arguments - 箭头函数没有
prototype
for of
未来,当遇到索引数组和类数组对象时,就用for-of
索引数组
var list = ["蓝蓝", "红红", "绿绿"];
for (var name of list) {
console.info(name)
}
类数组对象
这里讨论的是arguments
function fun1(value) {
console.info(arguments)
console.info(typeof arguments) // 对象
console.info(Array.isArray(arguments)) // false
for(var v of arguments){
console.info(v)
}
}
fun1("val")
上面代码就能判断出,arguments是一个对象,但是是类数组对象
函数的参数增强
参数默认值
function fun1(val = "defaultValue") {
console.info(val)
}
fun1();
fun1("传入的参数");
剩余参数(rest)
注意:rest是数组
function add(...rest) {
console.info(rest)
console.info(Array.isArray(rest)) // true
return rest.reduce((a, b) => a + b)
}
add(1, 2, 4, 5)
解构
- 数组解构
var arr = [2022, 3, 4];
var [y, m, d] = arr;
- 对象解构
var obj = {
y: 2022,
m: 3,
d: 4,
}
var { y, m, d } = obj;
class和继承
class本质是构造函数
class Student {
constructor(name, age) {
this.name = name;
this.age = age;
}
// intr保存在原型对象中
intr() {
console.info(this.name)
}
}
var lilei = new Student("lilei", 12)
直接放在class对象中的方法,就是原型对象方法
多个对象共用的相同属性值,应该放在哪?
注意问的是属性值
答案是:原型对象(prototype)上
class中的问题
直接在class中定义的方法,都默认保存在原型对象中。
但是直接在class中定义的属性,却不会成为公共属性,不会保存在原型对象中
class Student {
className = "二(8)班"
}
var lilei = new Student();
从上面可以看到,className属性是放在
实例上的
解决办法
使用静态属性
标有static的属性,都存在构造函数上
class Student {
static className = "二(8)班",
intr() {
console.info(this.className); // undefined
console.info(Student.className); // 通过类型名访问静态属性
}
}
var lilei = new Student();
注意看上图,static className到底存在哪?是Student这个构造函数身上
另外:上面代码有标注,如果想访问静态属性值,不可以通过this.静态属性。只能通过类型名.静态属性。
继承(extends)
- 先有子类型还是先有父类型?
答:现有子类型,发现子类型重复了,再去抽象父类型
super
- super是专门指向父类型的关键字
- 调用
super()等于调用父类型的构造函数 - 调用爷爷类型的构造函数,等效于执行爷爷类型的构造函数中共有的"this.xxx=xxx"语句
Promise
多个异步任务顺序执行
new Promise((resolve, rejected) => {
// do something
if(xxx) {
resolve(123);
} else {
rejected(444)
}
}).then((res) => {
console.info(res) // 123
}).catch((error) => {
console.error(error) // 444
})
async await
- 只有
基于Promise的函数,才支持async和await - await必须用在被async标记的函数中
- 外层函数必须用async标记,目的是告诉主程序,这段函数内的代码整体是异步执行的,不影响主程序的执行
- await必须写在前一项任务之前
- await的作用等效于
.then()。用来通知程序必须等待前一项任务执行完,才能继续执行后续任务 - 一旦使用await,前一项任务的resolve返回值,可以像普通函数一样用
=接住,后续代码可继续使用该变量里获得的返回值
async function test() {
var result = new Promise方法
console.info(result)
}
test()
- await和.then()一样,可多次使用,控制多个异步顺序执行
为什么函数前要用async标记
因为整个外层函数,相对于主程序,整个函数应该是异步的,不应该影响主程序。
同时告诉函数内的await,你们几个应该是同步的
错误处理
使用try catch