目录
12.3.1 startsWith()和endsWith()
重要部分>重点标注>次重要标注>理解说明>补充说明
1 概述
1.1 面向对象介绍
(1)面向过程 POP
分析出解决问题所需要的的步骤,然后用函数把这些步骤一步一步的实现
(2)面向对象OOP
把事务分解为一个个对象,然后由对象之间分工和合作
(3)面向过程和面向对象的对比
2 ES6中的类和对象
2.1 面向对象思维特点
2.2 对象
万物皆对象,对象是一个具体的事物,看得见摸得着的实物,在
js中对象是一组无序的相关属性和方法的集合,所有的事物都可以抽象为对象,属性事物的特征,方法事物的行为
2.3 类class
类抽象了对象的公共部分,它泛指某一大类,对象特指某一个,通过类实例化一个具体的对象
2.4 创建类
(1)创建类,class创建一个明星类,实例是类创建出来的对象
class Star{
constructor(uname) {
this.uname = uname;
}
}
(2)利用类创建对象new
var ldh = new Star('刘德华');
- 通过class关键字创建类,类名还是首字母大写
- 类里面有个constructor函数,可以接受传递过来的参数,同时返回实例对象
- constructor函数只要new生成示例时,就会自动调用这个函数,如果我们不写这个函数,类也会自动生成这个函数
- 生成示例new不能省略
- 最后注意语法规范,创建类,类名后面不要加小括号,生成实例 类名后面加小括号,构造函数不要加function
- class中所有的函数不需要加function
- 所有的函数中间不加,分割
(3)constructor 相当于创建的对象实例的构造函数的原型对象的constructor属性
(4)class在constructor外声明公用函数,其并不属于创建对象的方法,但可以实现多个对象公用的功能,节省了空间
2.5 类的继承
2.5.1 类的继承语法规范
class Father {
constructor() {
}
}
class Son extends Father {
constructor() {
super()
}
}
2.5.2 super关键字
(1) super关键字
调用了父类中的构造函数
- 子类的constructor中,可以使用super关键字,借用父类的constructor为子类的实例添加属性和方法
注意:在子类的constructor没添加属性和方法之前,必须要先调用 super
- 子类的实例可以调用父类的公共方法
注意:实例调用方法的时候,会优先调用自身方法,如果没有则调用类的公共方法,如果没有则调用父类的公共方法.
(2) super关键字调用父类的普通函数
super.父类普通函数() 调用父类中的普通函数
继承中属性或方法查找的原则:就近原则
- 继承中,如果实例化子类输出一个方法,先看子类有没有这个方法,如果有就先执行子类的
- 继承中,如果子类里面没有,就去查找父类有没有这个方法,如果有,就执行父类这个方法
(3) 实例:子类继承父类方法,同时扩展减法方法
// 父类有加法方法
class Father {
constructor(x, y) {
this.x = x;
this.y = y;
}
sum() {
console.log(this.x + this.y);
}
}
// 子类继承父类加法方法 同时 扩展减法方法
class Son extends Father {
constructor(x, y) {
// 利用super 调用父类的构造函数
// super 必须在子类this之前调用
super(x, y); //已经从父类中继承获得x,y属性,不需再次创建
}
subtract() {
console.log(this.x - this.y);
}
}
var son = new Son(5, 3);
son.subtract();
son.sum();
在ES6中没有变量提升,所以必须先定义类,才能通过类实例化对象
类里面的共有属性和方法一定要加this并使用super,表示复制父类的属性和方法,在继承时必须书写
2.5.3 this的指向问题
(1)this指向的是并不是特定的对象,而是在运行中,谁调用就指向谁
(2)constructor里面的this指向的是实例对象(new关键词创建新实例时,会调用构造函数,而构造函数本身this并没有什么意义,只有在new时才会变化,并将this指向实例)
2.6 添加新元素新方法
(1)element.insertAdjacentHTML(position,text)
不同于appendChild,这可以直接追加字符串识别为新标签,把text添加到父元素的指定位置。
position取值
beforebegin:插入到标签开始前——前面的兄弟
afterbegin:插入到标签开始标记之后——第一个子标签
beforeend:插入到标签结束标记——最后一个子标签
afterend:插入到标签结束标记后——后面的兄弟
3 js注意点和补充
(1)getElementsByTagName和getElementsByClassName是一个动态的集合(页面结构发生变化-删除添加)结果也会自动变化
(2)(防止index小于1,无法获取到元素的写法)
(3)获取元素时如果没有获取到,得到的结果是null。
(4)if 语句可以简写,如果花括号内只有一句话可以省略,但是有两句话以上时,不可以省略
(5)window.getSelection().toString获得选定的文字
4 构造函数和原型
4.1 概述
4.2 构造函数
4.2.1 静态成员和实例成员
(1)静态成员(构造函数本身的属性和方法)
在构造函数本身上添加的成员
静态成员只能通过构造函数来访问
(2)实例成员(构造函数创建出来的对象中的属性和方法)
就是构造函数内部通过this添加的成员实例成员只能通过实例化的对象来访问(不可以通过构造函数来访问)
4.3 构造函数原型prototype
原型对象:每一个构造函数都有这个属性
- 我们可以把那些不变的方法,直接定义在prototype对象中,这样所有的实例就可以共享这些方法
- 一般情况下,我们公共属性定义到构造函数里面,公共的方法我们放在原型对象身上
- 原型对象在函数对象被创建的时候就一起就创建了
- 原型对象的属性和方法,能够被函数创建的实例调用
- 实例调用属性、方法的时候,如果自身已经有了该属性、方法,则不会调用原型对象的属性和方法
- 实例对象中没有prototype中的属性和方法,但是可以被实例调用
4.4 对象原型__proto__(两边是两个下划线)
(1)对象会有一个属性__proto__指向构造函数中的原型对象
对象身上系统自动添加一个__proto__,对象中的原型和构造函数中的原型对象是等价的
(2)方法查找规则:首先先看ldh对象身上是否有sing方法,如果有就执行这个对象上的sing
如果没有这个方法,因为有__proto__的存在,就去构造函数原型对象prototype身上去查找sing这个方法
__proto__对象原型的意义就在于为对象的查找机制提供一个方向,或者说一条路线,但是他是一个非标准属性,因此实际开发中,不可以使用这一个属性(可以修改,但是修改后改变的是构造函数中的原型对象,而不是实例中__proto__,所以实际开发中不推荐这么使用),它只是内部指向原型对象prototype
4.5 原型constructor
实例的对象原型和构造函数原型对象里面都有一个constructor属性,这个属性我们称为构造函数,因为它指回构造函数本身
constructor: 构造函数名(原型对象中constructor相当这个操作)
4.6 构造函数、实例、原型对象三者之间的关系
4.7 原型链
(1)只要有对象就有__proto__原型,指向原型对象(相当于每个对象都是由一个构造函数(Object)实例化的(可以这么理解,因为可以通过var xx = new Object()创建空对象,),并由__proto__指向它Object的原型对象)
(2)我们star原型对象里面的__proto__原型指向的是Object.prototype
对象原型__proto__来自于构造函数的原型对象,在实例中展示的是原型对象。
(3) 补充:
通过构造函数实例化的对象,__proto__指向构造函数的原型对象,然后原型对象中__proto__指向Object构造函数,但构造函数本身的__proto__指向为Function这个构造函数,然后再指向Object构造函数
4.8 原型对象中this的指向
原型对象函数里面的this指向的是,实例对象(一般情况)
4.9 扩展内置对象
(1)Object.getPrototypeOf(实例对象)返回的是构造函数的原型对象。
可以通过原型对象,对原来的内置对象进行扩展自定义的方法,比如给数组增加自定义方法
(Object和Array是每一个对象和数组通过对象原型指向原型对象的构造函数(通过构造函数创建的实例,会先指向构造函数的原型对象,后指向Object或Array中的原型对象),他原型对象的方法便成为了js中的内置数组或对象方法)
内置的构造函数Object等是不允许赋值的
5 继承
ES6之前,没有extends继承,通过构造函数+原型对象模拟继承,被称为组合继承
5.1 call()
(1)call()方法可以调用函数fn.call()
(2)修改函数里面的this指向
fn.call(需要被指向的对象,函数原来的参数)相当于通过call方法,让此对象调用函数。call使用时函数不加括号,加在call后面
5.2 利用构造函数继承父类型中的属性
Son.Prototype = Father.Prototype只是将父原型对象地址给子原型对象,他们指向的是同一个数据,所以修改son的原型对象也是在修改父原型对象
Son.prototype = new Father();通过这种方式才可以 //相当于将Son的原型对象变为father的实例对象,而他的__proto__指向father的原型对象prototype,所以son的实例也通过__proto__指向son的原型对象prototype
Son.prototype.constructor = son如果利用对象的形式修改了原型对象,别忘了利用constructor指回原来的原型对象
6 类的本质
类:创建对象的模板,本质还是一个函数,我们也可以简单的认为类就是构造函数的另外的一种写法
- 类有原型对象
- 类有constructor,并指回类的本身
- 类也可以通过原型对象,添加方法
- 语法糖:就是一种便捷写法,简单理解,有两种方法可以实现同样的功能,但是一种写法更加清晰、方便那么这个方法就是语法糖。
这两种方式相同,后者是语法糖
7 数组的迭代和遍历方法
7.1 数组方法
迭代方法: forEach()、map()、filter()、some()、every();
7.1.1 forEach()
三个参数,分别表示,数组元素、数组元素的索引号、数组本身
7.1.2 filter()
主要筛选数组,返回的是一个新的数组,三个参数,数组元素,索引,和数组
return中写条件
返回return条件为true的值到新数组
7.1.3 some()查找元素中是否有满足条件的元素
返回值是布尔值,如果查找到这个元素,就是true,反之false,三个参数
找到一个满足条件的元素,就停止循环。
7.1.4 forEach和som的区别
(1)forEach中return不会终止迭代(遍历元素)
(2)在some中遇到return true会终止遍历,效率更高(return true代表条件满足,有第一个满足条件的元素就会终止)
(3)filter不会终止迭代
(4)如果在数组找唯一的元素,最好用some。
7.2 字符串方法
(1)trim方法
去除字符串两侧空格,ele.trim(),返回一个新的字符串,不会去掉中间的空格
7.3 Object静态方法
7.3.1 object.keys(obj)
用于获取对象自身所有的属性
相当于for i in k
返回一个由属性名组成的数组
7.3.2 定义属性的相关特征
(1)Object.defineProperty()定义对象中新属性或修改原有的属性
Object.defineProperty(对象,"添加或修改的属性",descriptor(以对象形式{}书写)):
descriptor:
- value:设置属性的值,默认为undefined
- writable:值是否可以重写。true | false 默认为false
- enumerate:目标属性是否可以被遍历。true | false 默认为false
- configurable:目标属性是否可以被删除或是否可以再次修改特性true | false 默认为false
8 函数进阶
8.1 函数的定义和调用
8.1.1 函数定义方式
(1)函数声明function关键字(命名函数)
(2)函数表达式
var fn = function() {}
(3)利用new Function(‘参数一’,‘参数二’,...,‘函数体’)
var f = new Function(‘console.log(123)’)
- 函数体和参数都是以字符串的形式书写
- 第三种方式执行效率低
- 所有的函数都是Function的实例(对象)
- 函数也属性对象
8.1.2 函数调用方式
(1)普通函数
fn();fn.call();
(2)对象的方法
var o = {sayHi:function(){}}; o.sayHi
(3)构造函数
function Star() {}; new Star();
(4)绑定事件函数
btn.onclick = function() {}; //触发事件调用
(5)定时器函数
每个一段时间调用一次
(6)立即执行函数 自己调用
8.2 this的函数指向
8.2.1 this的指向
(1)普通函数——window
(2)对象的方法------对象
(3)构造函数--------指向实例对象
(4)绑定事件函数-------指向函数的调用者,事件源
(5)定时器函数-------指向window
(6)立即执行函数--------指向window
8.2.2 改变函数内部this指向
(1)call方法 fn.call(被指向的对象,函数参数)
主要作用可以实现继承
var obj = {
name: 123,
fun: function() {
console.log(this)
function fn() {
console.log(this)
}
fn()
fn.call(this)
}
}
obj.fun.call(this) //window window window
第一步:改变对象方法的指向为window;第二步:方法内函数fn改变为对象的this指向(此时this已被改变为window),所以输出结果window window
(2)apply调用函数,也可以改变函数内部this的指向
- 但是他的参数必须是数组形式(伪数组)apply(被指向的对象,['1','2'])
- apply的主要应用:
- 利用apply借助数学内置对象求最大值等:Math.max.apply(Math, 数组) //指向没有改变,所以只是相当于调用Math.max方法,数组(apply传参方式)为此方法本来需要传递的参数.
(3) bind方法 绑定的意思
fn.bind(被指向的对象)
- 不会调用原来的函数
- 可以改变原来函数内部的this指向
- 返回的是原函数改变this之后产生的新函数,不会改变原函数
新函数传参进去会把形参替换成实参后,生成新函数(但形参的位置和形式还在)
新函数不传参,形参不被替换,可以正常使用新函数的形参
如果有的函数我们不需要立即调用,但是又想改变这个函数内部的this指向此时用bind
8.3 严格模式
8.3.1 开启严格模式
(1)为脚本开启
最上面写,为整个脚本开启严格模式
(2)为函数开启严格模式
function fn() {
'use strict';
//函数内部下面按照严格模式执行
}
8.3.2 严格模式中的变化
(1)变量
(2)严格模式this的指向
(3)函数的变化
不能再函数之外的{}中声明函数
8.4 高阶函数
是对其他函数进行操作的函数,它接收函数作为参数或将函数作为返回值输出
8.5 闭包*
8.5.1 变量作用域
8.5.2 什么是闭包
闭包指可以被另外一个函数访问其变量的函数
就是一个作用域可以访问另一个作用域中的变量
function fn() {
var num = 10;
function fun() {
console.log(num);
}
return fun
}
var r = fn();
r();
console.dir(r);
闭包的主要作用,延伸了变量的作用范围
上层作用域的变量,会通过[[Scopes]]属性存在闭包函数中,而这个属性中的 Closure对象就是我们需要的闭包数据,上层作用域里的变量数据,所以,造成内存被占用,一直不释放,数据较多时,会造成内存泄漏.可以实现外部访问闭包函数.一个作用域的变量互通
立即执行函数也称为小闭包
8.6 递归函数
8.6.1 什么是递归
如果一个函数内部可以调用其本身,这个函数就是递归函数
使用递归,很容易发生栈溢出,所以需要加退出条件(递归函数会等待函数调用完成,满足退出条件后,才依次结束)
<script>
var data = [{
id: 1,
name: '家电',
goods: [{
id: 11,
gname: '冰箱',
goods: [{
id: 111,
gname: '海尔'
}, {
id: 112,
gname: '美的'
},
]
}, {
id: 12,
gname: '洗衣机'
}]
}, {
id: 2,
name: '服饰'
}];
// 我们想要做输入id号,就可以返回的数据对象
// 1. 利用 forEach 去遍历里面的每一个对象
function getID(json, id) {
var o = {};
json.forEach(function(item) {
// console.log(item); // 2个数组元素
if (item.id == id) {
// console.log(item);
o = item;
return o;
// 2. 我们想要得里层的数据 11 12 可以利用递归函数
// 里面应该有goods这个数组并且数组的长度不为 0
} else if (item.goods && item.goods.length > 0) {
o = getID(item.goods, id); //getID这里只是一次函数的调用,和原函数getID是两个不同的函数,
//有不用的作用域,所以这两者的变量不通用,这里的调用给o赋值并不会改变原本o的值,所以需要o来重新接受该函数的返回值。
}
});
return o;
}
console.log(getID(data, 1));
console.log(getID(data, 2));
console.log(getID(data, 11));
console.log(getID(data, 12));
console.log(getID(data, 111));
</script>
8.7 浅拷贝和深拷贝
浅拷贝只是拷贝一层,对深层次对象级别的只拷贝引用
深拷贝拷贝多层,每一级别的属性都会拷贝
浅拷贝语法糖:Object.assign(需要拷贝, 被拷贝的数据 );
深拷贝语法:
// 深拷贝拷贝多层,每一级别的数据都会拷贝
var obj = {
id: "1",
name: "andy",
msg: {
age: 18
},
color: ['pink', 'red']
}
var o = {};
// 封装函数
function deepCopy(newObj, oldObj) {
for (var k in oldObj) {
// 判断我们的属性属于那种数据类型
// 1. 获取属性值 oldObj[k]
var item = oldObj[k];
// 2. 判断这个值是否是数组
if (item instanceof Array) {
newObj[k] = [];
deepCopy(newObj[k], item);
} else if (item instanceof Object) {
// 3. 判断这个值是否是对象
newObj[k] = {};
deepCopy(newObj[k], item);
} else {
// 4. 属于简单数据类型
newObj[k] = item;
}
}
}
deepCopy(o, obj);
数组也属一种特殊的对象,所以写深拷贝时需要先写数组,
9 正则表达式(听说非常简单)
9.1 概述
匹配字符串中的字符组合,是有规律的一种表达式,作为一种对象存在
(1)匹配输入框中内容(匹配)
(2)替换过滤内容中的一些敏感词(替换)
(3)从字符串中获取我们想要的特定部分。(提取)
(4)验证表单是否符合规则(验证)
9.2 表达式的缺点
9.3 创建正则表达式
(1)利用RegExp对象来创建
var 变量名 = new RegExp();
(2)利用字面量创建
var 变量名 = /内容/
9.4 测试正则表达式test()方法
9.5 正则表达式中的特殊字符
元字符: 有特殊意义的字符
边界符^ $
(1)/abc/包含即可
(2)/^abc/必须以adc开头
(3)/abc$/必须以abc结尾
(4)/^abc$/精确匹配abc
9.6 字符类
[]有一系列字符可供选择,只要匹配其中一个就可以了
[^abc$]三选一只有a或b或c这三个字母才返回true
9.6.1 [-]范围符
[a-z]a到z的范围,26个英文字母有任意一个即可
字符组合/^[a-zA-Z0-9]$/只能输入范围中的一个
[^]尖括号里面的^代表取反
| 将正则表达式一分为二,将需要或逻辑的表达式用小括号包裹起来,可以表示或。注意:在中括号中表示一个字符|
9.6.2 量词符
用来设定某个模式出现的次数,只修饰紧挨着 的前面的一部分,可以用圆括号包裹作为一部分
*规定了出现了0次或很多次
+规定了可以出现1次或很多次
?相当于出现零次或一次
{n}重复n次
{n,}大于等于n次
{n,m}n-m次
()表示的是优先级
input事件,在表单元素输入的时候触发
onchange事件,表单元素的值被改变、失去焦点
onblur事件,时区焦点
9.7 预定义类
9.8正则表达式中的替换
replace()
ele.replace('被替换的字符'/正则表达式,替换的字符)
replace只替换第一个满足条件的字符。
解决方法: /表达式/[switch]
switch也称修饰符,按照什么样的模式来匹配,有三种值
g:全局匹配
i: 忽略大小写
gi:全局匹配+忽略大小写
10 ES6简介
10.1 let关键字
(1)特性:
- let声明的变量只在所处于的块级有效 (用{}可以限制变量的使用范围:for循环中声明的i是局部变量);
- 在一个大括号中,使用let关键字声明的变量才具有块级作用域,var关键字没有此特点
- 防止循环变量变为全局变量
- 使用let声明的变量没有变量提升
- 使用let声明的变量具有暂时性死区(一个块级作用域中,如果有变量生成,就只能使用声明的变量,声明前不能使用,声明之后可以正常使用(全局变量的访问只能是在块级作用域中没有声明同名变量时有效,若存在同名变量也是依照暂时性死区看待),使用var声明的变量具有变量提升
10.2 conset声明常量
(1)作用:声明常量,常量就是值(内存地址)不能变化的量
(2)特征:
- 具有块级作用域
- 没有变量提升
- 有暂时性死区
- 声明常量是必须赋初始值
- 常量赋值后,值不能修改(指的是值对应的内存地址不可更改,复杂数据类型数据结构内部的值可以更改,但复杂数据本身不可更改)
10.3 let、const、var的区别
11 数据解构赋值(语法糖)
11.1 数组解构
- ES6中允许从数组中提取值,按照对应位置,对变量赋值,对象也可以实现解构。
- 数组解构 let[a, b, c] = arry允许我们按照一一对应的关系从数组中提取值,然后将值赋值给变量
- 假如对应的变量比数组中的元素多时,多出来的变量的值是undefined。
- 假如对应的变量比数组中的元素少时,只接受对应的值。
- 使用',,'空出来位置,可以跳跃赋值
11.2 对象解构
(1)对象解构允许我们使用变量的名字匹配对象的属性,匹配成功将对象属性的值赋值给变量
按照属性名称去匹配对应的数据,和顺序无关
(2)匹配左侧属性名,匹配成功,将右侧属性的值赋值给左侧属性名冒号后的变量。
这两者可以混合写
11.3 箭头函数
(1)箭头函数式用来简化函数定义语法的
() => {};
const fn = () => {};
(2)特点
函数体中只有一句代码,且代码的执行结果就是返回值,可以省略大括号
如果形参只有一个,可以省略小括号
不能使用arguments
11.3.1 箭头函数this
箭头函数不绑定this,箭头函数中的this,指向的是函数定义位置的上下文this,且永远不会被改变(且不会被bind,call等改变)
11.4 剩余参数
剩余参数语法允许我们将一个不定数量的参数表示为一个数组
var fn (a,b,...demo)=> console.log(demo);
剩余元素必须写在最后
fn(11,22,33,44,22)//demo接收的是实参匹配形参后剩余的实参。
11.5 扩展运算符(展开语法)
var arr = [3, 5, 7] ...arr //3, 5, 7
扩展运算符可以将数组拆分成逗号分隔的参数序列,console.log(..arr) //1 2 3
应用:(1)合并数组 let arr1 = [1, 2, 3]; let arr2 = [4, 5, 6]; let arr3 = [...arr1,...arr2] 或者 arr1.push(...arr2);
(2) 对象的扩展运算符
12 扩展方法
12.1 Array.from()
将伪数组转换为真正数组的方法(使用的是构造函数Array的方法,不是实例方法)
参数:
第一个参数表示要转换的伪数组
第二参数是一个函数,数组中每一项需要处理的程序,该函数参数item可以接收元素的值,return后写处理的程序。
12.2 数组实例的方法
12.2.1 find方法
用于找出第一个符合条件的成员对象,如果没有找到返回undefined(也会遍历数组,如果找到第一项满足条件的结果就会停止遍历)
array.find(item => 条件)
12.2.2 findIndex方法
用于找出第一个符合条件的数组成员的位置,如果没有找到返回-1
array.findIndex(item => 条件)
12.2.3 includes方法
表示某个数组中是否包含给定的值,返回布尔值
array.includes(需要判断的元素)
只能判断字符串
12.3 字符串实例方法
12.3.1 startsWith()和endsWith()
判断字符串是否以某一个字符开头或结尾,返回值是true和false
12.3.2 repeat方法
表示将原字符串重复n次,返回一个新的字符串
13 set数据结构
13.1 set创建实例
ES6提供了新的数据结构Set,它类似于数组,但是成员的值都是唯一的,没有重复的值。
- Set本身是一个构造函数,用来生成Set数据结构
- Set创建实例的时候可以传递参数,作用初始值,实现初始化
- 传递多个参数时,需要使用[]形式传入
- set创建的实例不允许有重复的元素,假如传递的初始值有重复,会去重后存储(会把后面重复的去除,保留前面)
set.size 属性可以得到set数据结构的长度
13.2 set实例方法
(1)add(value):添加某个值,返回Set结构本身,可以链式添加,add("a").add('b').add('c')
(2)delete(value):删除某个值,返回一个布尔值,表示删除是否成功
(3)has(value):判断某一个值,是否数据结构中的一员,返回值是布尔值
(4)clear():清空set数据结构中的值,返回set.size
13.3 遍历forEach
使用方法与数组遍历相同
13.4 利用set实现数组去重
var arr = ['a', 'b', 'c', 'a'];
arr = Array.from(new Set(arr));
14 promise对象补充
14.1 概述
Promise 对象代表了未来将要发生的事件,用来传递异步操作的消息。
Promise作用:解决异步回调的问题
(1)语法格式
var promise = new Promise(function(resolve, reject) { // 异步处理
// 处理结束后、调用resolve 或 reject });
注意:通过使用函数将其封装起来,调用的时候和then方法一同调用
14.2 特点
(1) 对象的状态不受外界影响。Promise 对象代表一个异步操作,有三种状态:
- pending: 初始状态,不是成功或失败状态。
- fulfilled: 意味着操作成功完成。
- rejected: 意味着操作失败。
只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。这也是 Promise 这个名字的由来,它的英语意思就是「承诺」,表示其他手段无法改变。
(2) 一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise 对象的状态改变,只有两种可能:从 Pending 变为 Resolved 和从 Pending 变为 Rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果。就算改变已经发生了,你再对 Promise 对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。
(3) 对于已经实例化过的 promise 对象可以调用 promise.then() 方法,传递 resolve 和 reject 方法作为回调,对异步的数据进行进一步的处理
(4) 有了 Promise 对象,就可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。此外,Promise 对象提供统一的接口,使得控制异步操作更加容易。
(5) 要想创建一个 promise 对象、可以使用 new 来调用 Promise 的构造器来进行实例化。
14.3 理解
promise对象为了处理异步任务,所以他的then方法虽然是异步进程,但执行优先度高于一般的异步进程(微任务).
then方法的作用在于将Resolved和reject接收的异步进程数据,进行进一步的异步处理,
15 Symbol补充
15.1 Symbol概念
ES6中引入了一种新的原始数据类型
常见的数据类型都有哪些
Symbol的作用
可以表示独一无二的值,比如定义对象的唯一属性名,定义不会重复的常量等等
15.2 语法
Symbol (description) // 描述信息可以有,也可以没有
var s = Symbol();
typeof s //Symbol
注意点:
- Symbol不是构造函数,不能使用new关键字,否则会有异常
- Symbol() 括号中内容代表symbol的描述,只是为了方便辨识,并不是它的值
- 每一个Symbol类型数据都独一无二,不会相等
- Symbol不能和其他值参与运算(不能进行隐式转换)
- Symbol可以显示的转为字符串,布尔值,但是不能转为数字型
15.3 Symbol 高级用法
场景: 使用Symbol可以定义对象的唯一属性名
这个属性不会被Object.keys或者for...in遍历到,起到保护个别隐私属性的作用
var s = Symbol();
var a = {};
a[s] = "xxx";
或者这种写法
注意点:
- Symbol值作为对象的属性名时不能使用点运算符
- 如果要访问Symbol的值要用a[s]的形式访问
- 这个属性不会被Object.keys或者for...in遍历到
16 js高级知识点补充
16.1 hasOwnProperty方法
存在于构造函数Object的原型对象prototype的一个方法
16.1.1 语法
实例对象调用此方法(传入一个参数,参数为需要判断的属性名)
const obj = new Object
obj.name = 'zs'
console.log(obj.hasOwnProperty('name')) // true
console.log(obj.hasOwnProperty('age')) // false
注:此方法只能判断自身具有的属性,不能判断构造函数上拥有的属性或方法(false)
16.2 数组的fill方法
将数组的一部分内容替换成传入的值
(1)语法
let arr = [1, 2, 3]
arr.fill(5, 1, 2) // [1, 5, 3]
(2)参数
参数1:表示需要替换的值
参数2:要替换的开始位置(从开始位置后替换)
参数3:要替换的结束位置
注意:当不传入参数的时候,将数组的全部内容替换
16.3 Object.assign() 方法
方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。
(1)参数
参数1:表示目标对象
参数2-x:表示源对象
(2)注意
- 该方法可以实现对象的浅拷贝,而不是对对象地址的引用(深拷贝)(只能实现第一层的拷贝,如果对象的属性仍是复杂数据类型,则只是引用地址)
- Object.assign 会跳过那些值为 null 或 undefined 的源对象。