所有字符串 API 都无权修改原字符串,
str.toUpperCase()
将字符串所有字母转为 大写
str.toLowerCase()
将字符串所有字母转为 小写
使用场景:不区分大小写进行判断的时候
var code = "EaS6";
do{
var codeInput = prompt("请输入验证码:" + code);
if(codeInput.toUpperCase() !== code.toUpperCase()){
alert("验证码错误,请重试");
}else{
break;
}
}while(true);
document.write("验证通过");
str[i] => str.charAt(i)
获取指定位置字符的 unicode 号
str.charCodeAt(i);
将 unicode 号反向转回字符
String.fromCharCode(i);
str.slice(strrt, end);
优点:支持附属参数,表示倒数
str.substring(start, end);
缺点:不支持附属参数 解决:str.length-n 代替 -n
str.substr(start, n)
n 表示个数
var i = str.indexOf(keyWord, from);
在 str 中,从 from 位置开始,找下一个 keyWord 所在位置
如果没有 from,默认从 0 位置开始
返回值:找到的第一个关键词的第一个字的下标位置
如果找不到,返回 -1
// 查找所有的关键词首字符下标
var str = "no zuo no die, no can no bibi";
var i = -1;
do{
var i = str.indexOf("no", i ++);
if(i != -1){
console.log(i);
}else{
break;
}
}while(true);
var i = str.lastIndexOf(keyWord);
在 str 中找最后一个 keyWord 的位置
var url = "http://tmooc.cn/imgs/logo.png";
var i = url.lastIndexOf("/");
var dot = url.lastIndexOf(".");
// 找出 url 中的 文件名 和 扩展名
var fileName = url.slice(i + 1);;
var extend = url.slice(dot);
console.log(fileName, extend);
问题:只能查找一种固定的关键词
解决:正则表达式
var i = str.search(/regexp/);
在 str 中查找第一个符合正则要求关键词位置,找不到,返回 -1
问题:正则默认区分大小写
解决:在第二个 /
后加 i
var i = str.search(/regexp/i);
注意:只能找 第一个 关键词的 位置
var arr = str.match(/正则/i);
在 str 中查找符合正则表达式要求的关键词,并将内容放入 arr 中
语法:
1. 默认只找第一个,但会返回位置
arr : [0: 关键词, index: 位置]
2. 查找所有关键词的内容
注意:只能获得关键词内容,无法获取位置
-
简单替换
将所有敏感词都替换为统一的值
var str = str.replace(/正则/ig, value);
-
高级替换
根据关键词的不同,动态选择不同的替换值
str = str.replace(/正则/ig, function(){
return kw.toUpperCase();
});
切割:用指定 分隔符 将字符串分割为多段 子字符串
- 简单切割:分隔符是固定的
str.split("");
固定套路:打散字符串为字符数组
- 复杂切割:分隔符不是固定的
str.split(/ /);
regular expression
概念:规定一个字符串中字符出现规律的规则
使用场景:
- 模糊查找多种敏感词
- 验证格式
形式:
-
一个关键词自身,就是一个最简单的正则表达式
-
字符集:
规定一位字符上多个备选字符列表的集合
只要一位字符上有多种字时
语法:[备选字符列表]
强调:一个字符集只能匹配一位字符
简写:如果备选字符列表中部分字符连接,可用
-
省略中间字符 常用简写:一位数字:[0-9]
一位小写字母:[a-z]
一位大写字母:[A-Z]
一位字母:[A-Za-z]
一位汉字:[\u4e00-\u9fa5]
除了:
[^xxx]
:除了xxx
都选中 EX: 车牌号:
[\u4e00-\u9fa5][A-Z]·[A-Z0-9][A-Z0-9][A-Z0-9][A-Z0-9][A-Z0-9]
-
预定义字符集
对常用字符集的进一步简写
\d
一位数字\w
一位字母,数字或 _\s
一位空字符:空格,tab,....
通配符
字符集的问题:只能固定一个字符,无法灵活定义数量;
解决:量词
-
量词
定义:规定一位字符出现次数的规则
when:只要规定字符出现的次数
how:字符集量词
强调:一个量词默认仅修饰相邻的前一个字符集
分类:
-
有明确数量范围:
{m, n} 至少 m 个,最多 n 个
{m,} 至少 m 个
{m} 只有 m 个
-
没有明确数量范围
? 可有可无,最多一个
* 可有可无,多了无限
+ 至少一个,多了无限
-
选择和分组
-
选择: 或 |
规则1 | 规则2
-
分组:(多个规则)
作用:将多个规则用 ()包裹为一组
why:量词默认只修饰相邻的一个字符集
when:只要希望一个量词同时修饰多个字符集的时候
EX: 身份证号:15位数字 + 2位数字 + 1位数字或X
\d{15}(\d{2}[0-9X])?
EX: 手机号: +86 | 0086 + 空字符 + 1 + [3-8] + 9位数字
(\+86|0086)?\s*1[3-8]\d{9}
-
-
匹配特殊位置
字符串开头:
^
字符串结尾:
$
when:仅希望匹配开头或结尾的内容时
EX: " zhang dong "
^\s+
仅匹配开头的空字符
\s+$
仅匹配结尾的空字符
^\s+|\s+$
即匹配开头,又匹配结尾的空字符单词边界: \b 包括:空格,标点,开头,结尾
- 匹配一个独立的单词时
\b[a-z]+\b
- 仅匹配单词开头或结尾的字母
\b[a-z]
[a-z]\b
- 匹配一个独立的单词时
专门封装一条正则表达式,并提供用正则表达式执行验证和查找的 API
只要用正则表达式执行验证和查找功能,都要用正则表达式对象
var reg = /RegExp/;
何时:如果正则表达式是固定的,不需要动态的生成
var reg = new RegExp("RegExp", "ig");
何时:如果正则表达式需要动态生成
var bool = reg.test(str);
用 reg 验证 str 的格式是否符合要求
问题:默认,只要 str 中部分和 reg 匹配,就返回
true
;解决 :
var reg = /^正则$/;
var arr = reg.exec(str);
在 str 中查找下一个符合 reg 要求的关键词的内容和位置
强调:一次只能找一个关键词
返回值:arr:[0: 关键词, index: 位置]
exec 可自动找下一个:
每个 reg 对象上有一个lastIndex 属性,开始为 0,记录着下次查找的位置
每次找到关键词,exec 自动修改 reg.lastIndex = 本次的位置 + 关键词长度
封装数学计算的常量和 API 的对象
只要执行数学相关计算
Math.ceil();
向上取整:只要超过,就取下一个整数
Math.floor();
向下取整:只要超过,就舍弃小数部分
parseInt(str)
能去掉数字后非数字字符(单位)
Math.round();
四舍五入
Math.round(); | n.toFixed(d); | |
---|---|---|
灵活 | 只能取整 | 可按任意小数位数取整 |
返回值 | Number 类型 | String 类型 |
Math.pow(num, n);
乘方
Math.sqrt();
开平方
Math.max();
最大值
Math.min();
最小值
问题:不支持获得数组中的最大值和最小值
解决:Math.max(...arr); // ... :ES6中的 spread 操作,打散数组为单个元素
0 <= Math.random();
< 1
公式: min ~ max
parseInt(Math.random() * (max - min + 1) + min);
Math.atan(对边 / 临边);
局限:只能在正负 45deg 内进行计算
解决:
Math.atan2( 对边长, 临边长);
定义:封装一个时间,并提供操作时间的 API
场景:只要在程序中存储时间或计算时间
创建方式:
-
创建日期对象,并自动获取当前系统时间
var now = new Date();
强调:只能获得客户端系统时间 => 用处不大,了解
-
创建日期对象并封装自定义时间
var birth = new Date("year/month/day h : m : s");
-
将毫秒数转化为日期对象 new Date();
日期对象本质:日期对象中实际保存的是 1970 年 1 月 1 日 至今的毫秒数
缘由:
用文字表示时间的两个问题
字符串不便于计算
受时区影响
用毫秒数的优点:
便于计算 不会受时区的影响 问题: 人看不懂,且没有 API 解决: 用 new Date(); 将毫秒数转为日期对象,并使用日期的对象提供的简化 API 操作时间 var date = new Date(ms);
-
复制一个日期对象
缘由:日期计算都是直接修改原日期对象
场景:如果希望同时保留计算前后的两个时间时
方式:var date2 = new Date(date1);
FullYear Month Date Day(周几)
Hours Minutes Seconds Milliseconds
每个单位上都有一对 get / set 方法
其中:date.getXXX(); 获取一个单位上的值
date.setXXX(num); 修改一个单位的数值
特例:Day 没有 set
单位 | 范围 | --=-说明 |
---|---|---|
Month | 0 ~ 11 | 计算机中的月份值比现实中小 1 |
Date | 1 ~ 31 | |
Day | 0 ~ 6 | |
Hours | 0 ~ 23 | |
Minutes / Seconds | 0 ~ 59 |
-
两日期对象可 相减 :结果是 毫秒差
-
对任意单位 加减 :
3 步:
- 取值: var now = new Date(); var d = date.getDate();
- 计算: d += 7;
- 改回去:now.setDate(d);
简写:
date.setDate(date.getDate() + 7);
福利:
setXXX(); 可自动调整时间进制
问题:
setXXX(); 直接修改原日期对象
解决:
先复制日期对象副本,再用副本计算
-
日期格式化:
API 描述 date.toString() 转为当地时间的完整格式 date.toLocaleString() 转为当地时间的简化版格式 date.toLocaleDateString() 当地时间格式,仅保留日期部分 date.toLocaleTimeString() 当地时间,仅保留时间部分
什么是:
当错误发生时,自动创建,封装错误信息的对象
什么是错误:
程序执行过程中,导致程序无法继续执行的异常情况
什么是错误处理:
即使程序出错,也不会中断推出的一种机制
为什么要进行错误处理:
程序只要出错,都会闪退
场景:
只要希望,即使程序出错,也不会中断退出
形式:try catch
try{ //可能出错的正确代码 }catch(e){ //只有出错时才触发 //错误处理代码 // 提示错误信息,保存进度,记录日志 }
问题:会额外创建错误对象,降低效率和浪费内存
解决:用 if else 提前预防错误发生
主动抛出错误:
throw new Error("错误提示");
定义:专门封装一段代码段的对象
场景:只要重用一段代码时
创建形式:
-
函数声明
function 函数声明(参数列表){
//函数体
//返回值
}
问题:声明提前(hoist)
-
函数表达式
var 函数名 = function(){}
优点:避免声明提前
-
new
var 函数名 = new Function("参数", "参数", ... , "函数体");
定义:相同函数名不同参数列表的多个函数,
在调用时,可根据传入参数的不同,自动选择匹配的函数执行
场景:只要一个函数根据不同的参数,执行不同的任务时
作用:减少 API 的数量,减轻调用者的负担
形式:JavaScript 默认不支持重载
原因:不允许多个同名函数同时存在
解决:arguments
定义:函数内自动创建的,收集所有传入函数参数值的 类数组对象
vs 数组:
相同: 1. 下标 2. length 3. 遍历
不同: 类型不同 API 不通用
场景:不确定传入函数的参数个数时
定义:函数创建后,不保存到任何变量的函数
场景:函数只调用一次时
作用:节约内存 =》匿名函数调用后自动释放
创建方式:
-
回调:创建函数后,自己不调用,而是给另一个函数去调用
EX:arr.sort(function(a, b){return a - b;});
arr.replace(/RegExp/ig,function(){return value;});
-
自调:函数定义后,立即调用自己
问题:禁止使用全局变量
理由:全局污染,内存泄漏
解决:用匿名函数自调包裹所有变量和操作
定义:即重用变量,又保护变量不被篡改的机制
原因:全局变量和局部变量都有不可兼得的优缺点
优点 | 缺点 | |
---|---|---|
全局变量 | 随处可用,可重复使用 | 造成全局污染和内存泄漏 |
局部变量 | 仅函数内可用 | 不可重用 |
何时:如果希望即重用一个变量,又保护变量不被篡改时
如何:3 步
- 用外层函数,包裹内层函数和受保护的变量
- 外层函数返回内层函数到外部
- 调用外层函数,获得内层函数引用,保存在变量中
程序中都是用对象结构来描述现实中一个具体事物
用途:描述现实中一个具体事物的程序结构
本质:内存中存储多个数据和函数的存储空间
作用:便于大量数据的维护
场景:今后,几乎所有程序都是面向对象的
特点:封装,继承,多态
创建一个对象,集中存储一个事物的属性和功能
作用:便于大量数据的维护
场景:只要使用面向对象方式编程,都要先封装对象,再使用对象操作数据
创建形式: 3 种
var obj = {
属性名 : 属性值 ,
方法名 : function(){
this.prototype
},
...
}
问题:对象自己的方法,要用自己的属性
错误:直接写属性名
因为不带任何前缀的普通变量,只能在作用域对象中找,无权擅自进入某个对象中查找
正确:即使对象
强调:即使对象自己的方法,想访问对象自己的属性,也要加 this
访问对象成员:成员 = 属性 + 方法
Obj.prototype;
对象.方法()
var obj = new Object();
obj.prototype = value;
揭示:起始 js 底层一切都是 关联数组
1. 可随时添加新属性
2. 如果访问不存在的成员,不报错,返回 undefined
3. obj.prototype = obj["prototype"];
如何选择:
1. 如果属性名时固定的,不需要动态生成,则首选 obj.prototype
2. 如果属性名需要动态生成,则只能用 obj["prototype"]
4. 都能用 for in 循环遍历
问题:一次只能创建一个对象
反复创建多个结构功能相同的对象时,代码冗余
解决:构造函数
概念:描述一类对象统一结构的函数
场景:如果需要反复创建多个相同结构的对象时
步骤:2 步
- 定义构造函数
function 类型名(属性参数列表){
this.prototype = values;
...
}
- 调用构造函数反复创建多个新对象
var obj = new 类型名(属性值列表);
new:4 件事
1. 创建新的空对象
2. 让新对象自动继承构造函数的原型对象
3. 调用构造函数,为新对象添加新属性
new 可将构造函数中的 this =》 新对象
通过为新对象强行赋值新属性的方式
返回新对象的地址保存在变量中
问题:反复创建方法,浪费内存
解决:继承
概念:父对象的成员,子对象无需重复创建,就可直接使用
作用:重用代码,节约内存
场景:多个对象拥有相同的方法定义时
形式:
继承原型对象
原型对象:集中存储多个子对象相同成员的父对象
场景:只要希望有成员可被多个子对象继承使用
语法:
创建:不用自己创建
在定义构造函数时,附赠一个原型对象
继承:不用手动 设置继承关系
new 创建子对象时,自动让子对象继承父对象
将公有的方法添加到原型对象中:
构造函数.prototype.方法 = function(){}
原型链 : 由多级父对象逐级继承形成的链式结构
概念:ES标准规定的,浏览器厂商已经实现的,我们直接使用的对象 / 类型
包括:11 个
String | Number | Boolean | ||
---|---|---|---|---|
Array | Date | RegExp | Math | |
Error | ||||
Function | Object | |||
global |
global (全局作用域对象,在浏览器中,用window代替)
特例:Math 不能 new,因为不是构造函数
global 也不能 new,因为已经是全局作用域对象
其余类型都由 2 部分组成:
- 构造函数:创建该类型的子对象
- 原型对象:保存该类型所有子对象共享的 API
String Number Boolean
概念:专门封装一个原始类型的值,并提供操作原始类型值的 API 的特殊类型
作用:原始类型的值本身什么 功能 / 属性 都没有
场景:只要用原始类型的值调用函数或访问属性时,都会自动使用包装类型
语法:
EX:
var n = 345.678; n.toFixed(2);
// typeof(n); // number
// new Number(n).toFixed(2); // 345.68 => delete
bishi:判断一个对象是不是数组类型,共有集中方式
typeof 可区分原始类型,对象和函数,不能细致区分对象的具体类型
- 判断 原型对象
obj.__proto__ === Array.prototype
Array.prototype.isPrototypeOf(obj)
- 判断 构造函数
obj.constructor === Array
obj instanceof Array
问题:不够严谨
- 判断对象的 class (内部)属性
每个对象都有一个隐藏的 class 属性,只在创建对象时保存对象的类型名,之后不随继承关系改变
问题:无法用 . 直接访问
解决:只有顶级父对象 Obejct.prototype中的toString()方法才能输出对象的 class
问题:各类型的原型对象中都重写了 toString() 方法,子对象默认无法调用顶级父对象中的 toString()
解决: call()
语法: 函数名.call(对象)
作用:让对象强行调用调用本来调不到的
- Array.isArray(obj);
实例方法 静态方法(static) 概念 保存在类型的原型对象中,只允许当前类型的子对象使用。其他类型的子对象不能使用 不定义在原型对象中,任何对象都可以使用的方法 场景 只允许当前类型的子对象使用 任何对象都可使用 存储位置 所有实例方法都定义在原型对象中 直接添加到构造函数对象上 调用 必须先创建该类型的子对象,再用子对象调用 不用创建任何子对象,用构造函数直接调用
概念:同一个函数在不同情况下表现出不同的状态
形式:2 种
重载
重写 (override)
概念:如果子对象觉得从父对象继承来的成员不好用!
可在子对象本地定义同名成员,覆盖父对象同名成员
原因:子对象觉得从父对象继承来的成员不好用
场景:如果子对象觉得从父对象继承来的成员不好用
语法:在子对象本地定义同名成员,覆盖父对象同名成员
-
只修改一个子对象的父对象
child.__proto__ = father;
Object.setPrototypeOf(child, father);
-
修改所有子对象的父对象
构造函数.prototype = father;
强调:注意时机,定义构造函数后,立即更换!
-
两种类型间的继承:
问题:两种类型,拥有部分相同的属性结构和方法定义
解决:定义一个公共的抽象父类型
语法: 2 步
- 定义抽象父类型
- 定义父类型构造函数,包含相同的属性结构
- 定义父类型原型对象,包含相同的方法定义
- 让子类型继承抽象父类型
- 在子类型构造函数中借用父类型构造
问题:直接调用父类型构造函数,无法为子对象添加父类型中的属性
原因:直接调用一个函数,其中 this 默认指向 window
解决:call
函数.call(替换 this 的对象, 对象, ...);
将函数内的 this 替换为指定的对象,并传入参数
总结:将来,只要函数中的 this 不是想要的,都可用 call 替换
- 让子类型原型对象继承父类型原型对象
严格模式:比普通 js 运行要求更严格的模式
原因:js 语言本身有广受诟病的缺陷
场景:今后所有 js 程序,都要运行在严格模式下
如何:2 种
-
新项目: <script> 或 js 文件顶部:
"use strict"
-
旧项目维护:逐个模块向严格模式迁移
在 function 函数内部: "use strict"
包括:
-
禁止给未声明的变量赋值
解决:内存泄漏,全局污染
-
静默失败升级为错误
静默失败:执行不成功,也不报错
-
普通函数调用中的 this 不在默认指向 window
解决:内存泄漏,全局污染
-
不建议使用 arguments arguments.callee arguments.caller
arguments.callee 指参数列表自身函数引用,比如匿名函数自调
arguments.caller 参数列表自身函数执行的环境
ES5中对象属性分为:
内部属性:仅在对象内保存,不能用
.
直接访问的属性命名属性:可用
.
随意访问的属性,分两类数据属性:实际存储属性值的属性
访问器属性:不实际存储属性值,仅提供对另一个数据属性的保护
数据属性包含四大特性:{
value : 保存属性值 ,
writable : 控制是否可修改 ,
enumerable : 控制是否可被 for in 遍历 ,
configurable : 控制是否可被删除 && 控制是否可修改前两个特性
}
强调
- 通常修改 writable 和 enumerable 时,都将configurable 改为 false,双保险
- enumerable 只能防止不被遍历访问到,用
.
还是可以被访问获取一个属性的四大特性:
var obj = Object.getOwnPropertyDescriptor();
修改一个属性的四大特性:
Object.defineProperty(obj, "属性名", {
四大特性 : true / false
});
同时修改多个属性的四大特性:
Object.defineProperty(obj, {
属性名 : {四大特性之一 : true / false, 四大特性之一 : true / false, ...},
属性名 : {四大特性之一 : true / false, 四大特性之一 : true / false, ...},
属性名 : {四大特性之一 : true / false, 四大特性之一 : true / false, ...},
...
});
问题:无法用自定义规则保护属性
解决:访问器属性
概念:不存储属性值,仅提供对其他数据属性的保护
场景:用自定义规则保护属性时
语法:
前提:有一个被保护的数据属性
四大特性
{
get : function(){return 从受保护的数据属性中取值},
set : function(val){
if(true){
将 val 的值保存给受保护的数据属性
}else{
Error
}
},
enumerable : ture,
configurable : false
}
访问器属性只能用 Object.defineProperty 或 Object.defineProperties 添加,不能用直接量添加
用法:
访问器属性的用法和普通属性完全一样:
试图获取属性值时,自动调用 get 方法,
试图修改属性值时,自动调用 set 方法
其中 val 自动获得新值
3 个级别
Object.preventExtensions(obj)
原理:
每个对象中都隐藏着一个内部属性:extensible = true
Object.preventExtensions(obj) => extensible = false;
Object.seal(obj);
原理:
- extensible = false
- configurable = false
Object.freeze(obj)
原理:
- extensible = false;
- configurable = false;
- writable = false;
概念:仅基于一个现有父对象,创建子对象,并继承父对象
场景:如果没有构造函数,也想创建子对象时
语法:var child = Object.create(father, {
// 同 defineProperty
});
概念:替换函数中不想要的 this
-
call , apply
概念:调用一个函数,并 临时替换 this 未指定对象
语法:函数.call(对象 , 参数值 , ...)
call vs apply ? apply 要求传入的多个参数值 必须放在一个数组中整体传入
-
bind
概念:基于原函数,创建一个新函数,并永久绑定 this 和部分参数
代替 var, 用于声明提前
var 的问题 : 会被声明提前
let 的优点:不会被声明提前
原理:let 会检查,在 let 之前,不允许使用声明的变量
重要作用:
为程序添加了块级作用域:
块级作用域:if else while for do...while switch
问题:传统 js 没有块级作用域,块级变量很可能泄漏到外部,造成污染
解决:let 可将上面的 if .. 编程块级作用域,内部的变量只能在块内使用
原理:let 其实是 匿名函数自调
默认值:default
function fun(参数1, 参数2, ..., 参数n = 默认值){}
强调:有默认值的参数必须写在参数列表的末尾
原理:fromi = fromi || 0;
作用:代替 arguments
arguments 问题:
1. 不是纯正的数组类型
2. 只能获取所有参数,不能部分获取
场景:不确定参数个数
形式:function fun(参数1, 参数2, ... , ...数组){}
优点:
rest 能获得纯正的数组
可部分获得参数
调用函数 传参时,打散数组类型参数为单个值:
fun(参数1, 参数2, 参数3, ...){}
场景:如果函数要求单个参数值传入,而给定的参数是一个数组时
替代:fun.apply(null, 数组);
简化一切回调函数或匿名函数自调
去掉
function
,改为=>
更简化:如果函数体只有一条执行语句,可省略
{}
如果这条执行语句时
return
,一起省略 如果只有一个参数,可省略
()
强调:将普通函数改为箭头函数后,函数内的 this 与 外部的 this 通用、
总结:如果希望 函数内外的 this 不通用,不能使用箭头函数 简化!比如:事件处理函数
代替 +
拼接字符串
语法:将完整字符串包裹在 `` 中
作用:内部支持换行等格式
支持动态内容:${ 变量或表达式 }
简化对象属性 / 数组元素的使用:
场景:只要从对象 / 数组中挑选个别需要的属性或元素使用时
形式:3 种
从数组中挑出想要的元素来使用,下标对下标:
var [变量1, 变量2, ...] = [值1, 值2, ...]
变量 1 = 值 1,变量 2 = 值 2, ...
从对象中挑出想要的属性或方法来使用,属性对属性,方法对方法:
var {属性1:变量1, 属性2: 变量2,...} = {属性1:值1, 属性2: 值2,...}
变量1 = 值1, 变量2 = 值2, ...
问题:普通函数参数必须连续传入,不能间隔或跳跃
解决:参数解构
形式:2 步
1. 定义函数时,将参数列表定义为对象格式
2. 传参时,将所有参数值,放入对象中传入
作用:可以选择传入部分参数,且和顺序无关
最简化的遍历数组或类数对象的方法
遍历数组: 3 种
// 1.
for(var i = 0; i < arr.length; i ++){
var elem = arr[i];
}
// 2.
arr.forEach((elem, i, arr) => {
...
})
// 3.
for(var elem of arr){
...
}
注意:
for...of 只能遍历数组/类数组对象
for...in 专门遍历关联数组和对象属性
直接量
var obj = {
属性名 : 变量名 , // 如果变量名 == 属性名,只写一个即可
函数名(){}
}
构造函数
用 class 类型名 {} 包裹构造函数和原型对象方法
构造函数名提升为类型名,构造函数律变更为 constructor
直接定义在 class 中的方法,默认就保存进原型对象中
两种类型间正式的继承
- 用 extends 父类型,代替 Object.setPrototypeOf()
- 用 super
作用:代替所有异步回调(ex: ajax)
异步回调:在不影响主程序情况下,等待一段时间后,调用回调函数或触发事件
问题:callback hell
因为提前传入回调函数参数,导致嵌套层级很深
解决:Promise
封装一段任务,并提供一个向后继续执行
错误处理:
return new Promise(function(open, err){
// 如果正确执行,则打开
open() -> .then()
// 否则,打开
err("error msg") -> .catch()
}).catch((err) => { throw err })
说明:只需要在最后一个 .then
等待多项任务:
Promise.all([
fun(),
fun(),
]).then();