闲来无事,把之前的笔记整理一下。
基础知识
变量类型
- 值类型:a和b相等,改a,b不变 (直接赋值值)
- undefined string number boolean
- 引用类型:a和b相等,改a,b变 (赋值地址)
- object function
- 强制类型转换
- 字符串拼接
var a=10; var b=100 + '10'//string
- ==
100=='100'; 0==''; null==undefined //true
- if
if(b=100)//转换为true
- 逻辑运算符(&,||)
10&&0;''||'abc'; !window.abc//都转换为true或false
- 字符串拼接
- 问题
- typeof能得到哪些类型
- number, string, object, boolean, function, undefiend, symbol (null是object)
- symbol: 可以生成永不重复的值,可以用一个字符串标记
- 何时使用===,何时使用==
- ===:内容相等数据类型也相同的严格模式;==:内容相等数据类型可以不相等
- 使用==的唯一情况:’’if(obj.a==null){}’’
- typeof能得到哪些类型
原型 原型链
- 构造函数
function Foo(name,age) {this.name=name; this.age=age return this}
var f = new Foo('ted',20)
- var a ={}是var a =new Object()的语法糖//数组,函数同理
- 函数名大写字母开头
- 原型规则和示例
- 所有的引用类型(数组对象函数)都具有对象特性,即可自由扩展属性(null除外)
- 所有的引用类型都有一个
__proto__
属性,属性值是一个普通对象 - 所有的函数都有一个prototype属性,属性值也是一个普通的对象
__proto__
对象指向它的构造函数的prototype对象(完全等于)- 当试图得到一个引用类型的某个属性时,如果这个变量本身没有这个属性,那么会去它的
__proto__
,即它的构造函数的prototype中找 - 例子:不遍历原型上的属性:
if(f.hasOwnProperty(item))
- 原型链
- 一个对象,对象自身不存在的属性到它的隐式原型找,它的隐式原型不存的的话,再到它的隐式原型的隐式原型中找
- Object.prototype指向null,防止死循环
- instanceof
- instanceof判断一个函数是否是一个变量的构造函数
var f = new Foo('ted')
f instanceof Foo//true
- 判断逻辑:f的
__proto__
一层层往上,能否对应到Foo.prototype
- 问题
- 如何准确判断一个变量是数组
var arr = []
arr instanceof Array//true
- 写一个原型链继承的例子
function Animal(){this.eat = function(){console.log('eat')}}
function Dog(){this.bark(){console.log('bark')}}
Dog.prototype=new Animal()
var haski=new Dog()
//这个比较lowfunction Elem(id){this.elem=document.getElementById(id)}
Elem.prototype.html=function(val) {
var elem=this.elem if(val){ elem.innerHTML=val return this } else{ return elem.innerHTML}}</pre>
Elem.prototype.on=function(type,fn){
var elem=this.elem elem.addEventListener(type,fn) </pre>
var div1 = new Elem('div1')
- 描述new一个对象的过程
- 创建一个新对象
- this指向这个新对象
- 执行构造函数的代码,即对this赋值
- 返回this
- 如何准确判断一个变量是数组
作用域 闭包
- 执行上下文 代码执行的环境
- 一段
<script>
:全局上下文- 变量定义->函数申明
- 一个函数:函数上下文
- 变量定义->函数申明->this->arguments
- 一段
- this
- this要在执行时才能确认值,定义时无法确认
- call可以改变this的值:
a.fn.call({name:B})
- 1.作为构造函数执行:指向定义的对象
function Foo(name) {
this.name = name}
var f = new Foo(‘ted’) - 2.作为对象属性执行:指向该对象
var obj = {
name: ‘A’, printName: function () {console.log(this.name)}}
obj.printName() - 3.作为普通函数执行: 指向window
function fn() {
console.log(this)}} - 4.call apply bind
function fn1(name, age) {
alert(name); console.log(this)}
fn1(‘ted’,20)//普通函数的this,指向window
fn1.call({x:100},’ted’,20)//通过call函数改变this,指向{x:100}这个对象
fn1.apply({x:200}, [‘ted’, 20])//apply和call不同在于参数用数组传递//bind:适用于函数表达式 var fn2 = function (name, age) { alert(name); console.log(this)} .bind({y:300}) fn2('ted',20)//通过bind函数改变this,this也指向{y:300}这个对象
- 作用域
- JS没有块级作用域
- 在函数中定义和赋值的变量可以在函数外使用
- ES6中加入块级作用域:
for(let i = 0; i< 10; i++){}
console.log(i)//报错,let定义的变量有块级作用域,在for中定义的不能在for之外访问
- JS有函数和全局作用域
- 定义在函数中的变量,只能在函数中修改
- 自由变量:当前作用域没有定义的变量,可以在父级作用域中去找
- JS没有块级作用域
- 作用域链
- 当前作用域可访问父级作用域
- 一个元素的父级作用域是在它定义的时候的作用域,而非执行
- 闭包
- 函数作为返回值
- 函数作为参数传递
- 闭包中返回的函数,若有自由变量,则向(函数定义时)父作用域寻找
问题
- 说一下对变量提升的理解
- 在各个执行上下文中,变量定义+函数声明都会提前
- 说明this几种不同的使用场景
- 作为构造函数:指向定义的对象
- 作为对象属性:指向该对象
- 作为普通函数:指向window
- call apply bind: 指向改变的对象
- 创建10个
<a>
标签,点击的时候弹出来对应的序号
* - 如何理解作用域
- 自由变量
- 作用域链,自由变量的查找
- 闭包的两个场景
- 闭包
实际开发中闭包的应用
封装变量,收敛权限
let isFirstLoad = function () { let _list = [] return function (el) { if (_list.indexOf(el) >= 0) { return false } else { _list.push(el) return true } } } let firstLoad = isFirstLoad() isFirstLoad(10) //true isFirstLoad(10) //false isFirstLoad(20) //true
- 说一下对变量提升的理解
异步和单线程
- 什么是异步(对比同步)
- 同步会阻塞,异步不会,遇到setTimeout会先执行后面的代码
- 何时使用:有可能发生等待的情况-等待的过程不能阻塞程序运行
- 前端使用异步的场景
- 定时任务:setTimeout,setInverral
- 网络请求:ajax请求,动态加载 (时间不固定)
- 事件绑定:如点击事件,在不点击的时候不能阻塞程序运行
- 异步和单线程
- 单线程:代码一个个排队执行,不能同时干两件事
- js是单线程,所以在遇到阻塞的情况,要用异步,现将不需要等待的代码执行完,再执行异步代码
- 问题
- 同步和异步的区别是什么?分别举一个同步和异步的例子
- 同步会阻塞代码,异步不会,alert是同步,setTimeout是异步
- 一个关于setTimeout的笔试题
- 前端使用异步的场景有哪些?
- 定时任务-网络请求-时间绑定
- 同步和异步的区别是什么?分别举一个同步和异步的例子
补充
日期
Date.now() //获取时间戳 //2019/09/17/23:41:44 let dt = new Date() dt.getTime() //获取时间戳 dt.getFullYear() //2019 dt.getMonth() //8 (0-11) dt.getDate() //17 (0-31) dt.getHours() //23 (0-23) dt.getMinutes() //41 (0-59) dt.getSeconds() //44 (0-59)
Math
- 获取随机数
Math.random()
- 获取随机数
- 数组api
- forEach 遍历所有元素
- every 判断所有元素是否都符合条件
- some 判断是否有至少一个元素符合条件
- sort 排序
- map 对元素重新组装,生成新数组
- filter 过滤符合条件的元素
- 对象api
- for in
题目
获取2019-07-25格式的日期
let formatDate = function (dt) { if (!dt) { dt = new Date() } let year = dt.getFullYear() let month = dt.getMonth() + 1 let date = dt.getDate() if (month < 10) { month = '0' + month } if (date < 10) { date = '0' + date } return year + '-' + month + '-' + date } let dt = new Date() console.log(formatDate(dt))
获取随机数,要求是长度一致的字符串格式
//获取长度一致的随机数 let formatRandom = function () { let random = Math.random() random = random + '0000000000' return random.slice(0, 10) } console.log(formatRandom())
JS API
- JS语法标准(基础知识):ECMA 262标准
- JS-WEB-API(浏览器):W3C标准
- DOM操作
- BOM操作:浏览器操作 获取当前地址 获取屏幕尺寸
- 事件绑定
- AJAX请求(包括http协议)
- 存储
- 没有规定任何JS基础相关的东西
- 全面考虑,JS内置的全局函数和对象(浏览器打造)
- Object,Array,Boolean等
- window document
- 所有未定义的全局变量,如navigator.userAgent
DOM操作
- DOM本质
- 浏览器拿到html代码后,把html结构化成浏览器可识别以及js可识别的东西,就是dom
- dom本质是js的对象
DOM节点操作
获取dom节点
//获取DOM节点 //get let id1 = document.getElementById('id1') //id let divs = document.getElementByTagName('div') //元素集合 let div0 = document.getElementByTagName('div')[0] //元素 let classes = document.getElementsByClassName('class1') //class集合 let class0 = document.getElementsByClassName('class1')[0] //class //query let id1 = document.querySelector('#id1') //id let divs = document.querySelectorAll('div') //元素集合 let div0 = document.querySelector('div') //元素,选择第一个div let div0 = document.querySelector('div')[0] //元素,选择第一个div let classes = document.querySelectorAll('.class0') //class集合 let class0 = document.querySelector('class0') //class,选择第一个class let class0 = document.querySelector('class0')[0] //class,选择第一个class
property
js对象中的属性
//获取attribute let p0 = document.quertSelectorAll('p')[0] console.log(p0.style.width) //获取样式 p0.style.width = '200px' //修改样式 console.log(p0.className) //获取class p0.className = 'p0' //修改class console.log(p0.nodeName) //p console.log(p0.nodeType) //1
attribute
HTML文档中 标签的属性
//获取attribute let p0 = document.querySelectorAll('p')[0] p0.getAttribute('attr1') //获取p0上的attr1属性的值 p0.getAttribute('attr1', 'abc') //修改属性 p0.getAttribute('style') //获取style,元素上必须有style才行 p0.getAttribute('style', 'font-size:30px')
DOM结构操作
新增节点
document.createElement(node)
//添加新节点 let div1 = document.getElementById('div1') let p1 = documemt.createElement('p') div1.appendChild(div1) //移动现有节点 let p2 = document.getElementById('p2') div1.appendChild(p2)
获取父节点
childNode.parentElement
let div1 = getElementById(div1) let parent = div1.parentElement
获取子节点
.parentNode.childNodes
let div1 = getElementById(div1) let parent = div1.parentElement
.childNodes
返回所有节点包括文本和注释节点.children
只返回元素节点
删除节点
parentNode.removeChild(childNode)
let div1 = getElementById(div1) let child = div1.childNodes //删除第一个子元素 div1.removeChild(child[0])
问题
- DOM是哪一种基本数据结构
- 数
- DOM操作的常用API有哪些
- 获取DOM节点,以及节点的property和attr
- 获取父节点,子节点
- 新增,删除,移动节点
- DOM节点的attr和property有何局别
- property是js属性的修改和获取
- attr是对html标签的修改和获取
- DOM是哪一种基本数据结构
BOM操作
- navigator浏览器
- 判断浏览器类型 userAgent
var ua = navigator.userAgent
var isChrome = ua.indexOf(‘Chrome’)
console.log(isChrome)
- 判断浏览器类型 userAgent
- screen屏幕
console.log(screen.width) console.log(screen.height)
- location地址栏信息 拆解url
location.href //url location.protocal //协议 http https location.host //域名 location.pathname //路径 /learn/199 location.search //url ? 后面的字符串 location.search //url # 后的hash
history历史 前进后退
history.back history.forward
问题
如何检测目标浏览器的类型
let ua = navigator.userAgent let isChrome = ua.indexOf('Chrome') console.log(isChrome)
拆解url的各部分
location.href //url location.protocal //协议 http https location.host //域名 location.pathname //路径 /learn/199 location.search //url ? 后面的字符串 location.search //url # 后的hash
Ajax
XMLHttpRequest
let xhr = new XMLHttpRequest() xhr.open("GET", "/api", "false") xhr.onreadystatechange = function () { if (xhr.readyState === 4) { if (xhr.status === 200) { alert(xhr.responseText) } } } xhr.send(null)
状态码说明
readyState == 4
ajax状态码- 0-(未初始化)还没有调用send()方法
- 1-(载入)已调用send()方法,正在发送请求
- 2-(载入完成)send()方法执行完成,已经接收到全部响应内容
- 3-(交互)正在解析响应内容
- 4-(完成)响应内容解析完成,可以在客户端调用了
statue == 200
http标准状态码- 2xx - 表示成功处理请求。如200
- 3xx - 需要重定向,浏览器直接跳转
- 4xx - 客户端请求错误,如404
- 5xx - 服务端错误
跨域
- 什么是跨域
- 浏览器有同源策略,不允许ajax访问其他接口,如http://www.a.com:80不能访问http://www.b.com
- 跨域条件:协议(http)、域名(www.a.com)、端口(:80)有一个不同就算跨域
- 可以跨域的三个标签
<img src=xxx>
- 用于打点统计,统计网站可能是其他域
<link href=xxx>
- 可以使用CDN,CDN也是其他域
<script src=xxx>
- 可以使用CDN,CDN也是其他域
- 可以用于JSONP
JSONP 前端
<!-- jsonp跨域 --> <script> function callbackFunc (data) { alert(data) } </script> <script src="http://www.baidu.com/api/data.js"></script>
- 前端定义一个callback函数,得到信息。再用script标签获取一个跨域的信息,这个信息会调用callback({x:100, y:200})
服务器端设置http header 后端
//后端通过设置httpheader跨域 response.setHeader("Access-Control-Allow-Origin", "http://a.com, http://b.com"); response.setHeader("Access-Control-Allow-Headers", "X-Requested-With"); response.setHeader("Access-Control-Allow-Methods", "PUT, POST,GET, OPTIONS, DELETE"); //允许接收跨域的cookie response.setHeader("Access-Control-Allow-Credentials", "true");
- 什么是跨域
问题
- 手动编写一个ajax,不依赖第三方库
- 前面有
- 跨域的几种实现方式
- JSONP
- 服务器端设置http header
- 手动编写一个ajax,不依赖第三方库
事件绑定
通用事件绑定
//通用事件绑定函数 function bindEvent (elem, type, fn) { elem.addEventListener(type, fn) } let a1 = document.getElementById('a1') bindEvent(a1, 'click', function (e) { e.preventDefault() alert('clicked') })
事件冒泡
- 若底层和父层节点有相同绑定事件,底层业务节点的事件(如点击)会先执行,然后会一层层网上执行,先执行底层的事件,然后上一层的事件,然后…
- 点击激活弹出激活,点击取消弹出取消
(e.stopPropatation()
:阻止冒泡)
代理 事件冒泡的应用
点击a标签的元素,会弹出相应文字
`
<!DOCTYPE html>
propogation
```
(这里target可以定位到当前点击的元素)
- 问题
- 编写一个通用的事件监听函数
- 描述事件冒泡流程
- dom树形结构
- 冒泡
- 阻止冒泡
- 应用:代理
- 对于一个无限下拉加载图片的页面,如何给每个图片绑定事件
- 使用代理:代码简洁,对浏览器压力小
存储
- cookie
- 属于http的东西,本身用于客户端和服务端通信
- 但是它有本地存储的功能,于是被“借用”
- 使用
document.cookie=...
获取和修改即可 - 限制:
- 存储量太小,只有4kb
- 所有http请求都带着,会影响获取资源的效率
- API简单,需要封装才能用
document.coockie
sessionStorage和localStorage
- H5专门为存储而设计,最大容量5M
- API简单易用,key+value
localStorage.setItem(key,value) localStorage.getItem(key)
问题
- 描述一下cookie(h5之前),sessionStorage和localStorage的区别
- cookie和后两者的区别
- 容量
- 是否会携带到ajax请求中
- API易用性
- 后两者的区别
- localStorage不会主动删除,sessionStorage随着每次会话结束会清除,95%的场景存储到localStorage中
- cookie和后两者的区别
- 描述一下cookie(h5之前),sessionStorage和localStorage的区别
开发环境
IDE(写代码的效率)
- webstorm
- sublime
- vscode
- atom
git 版本管理,多人协作
- 常用命令
- git add .
- git checkout xxx
- git commit -m ‘xxx’ //提交到本地仓库
- git push origin master
- git pull origin master
- git branch
- git checkout -b xxx
- git merge xxx
js模块化
- 不适用模块化的情况
- 如果a.js, b.js, c.js, c依赖b,b依赖a,引用的时候必须要按顺序,如果顺序错就会报错
- 引用的文件的变量必须是全局变量,容易被污染
- 使用模块化
- a.js 传递出别人所需要的功能函数,b和a需要哪个函数引用哪个函数
- 引用的时候直接引用最表层的js文件即可
AMD 异步模块定义规范
- require.js
- 全局define函数
- 全局require函数
依赖的js会自动、异步加载
`
//util.js
define(function() {return { func: function () { return 1 } }
})
//a-utils.js
define([‘./utils.js’], function(util) {return { func2: function () { return util.func() } }
})
```
* html用:``<script src="/require.js" data-main="./main.js"></script> ``
* 好处:异步加载,不使用(依赖)就不加载
CommonJs
- nodejs模块化规划,现在被大量用于前端
- 前端开发依赖的插件和库,都可以用npm中获取
- 构建工具的高度自动化,使得使用npm的成本非常低
CommonJS不会异步加载js,而是同步一次性加载出来
//util.js module.exports = { func: function () { return 1 } } //a-util.js let util = require('./util.js') module.exports = { func2: function () { return utils() } }
AMD和CommonJS的使用场景
- 需要异步加载,用AMD
- 使用了npm之后建议使用CommonJs
打包工具
webpack
- 启动一个服务,先全局安装,
npm install http-server =g
,然后在要访问的页面根目录启动服务http-server 8080
npm init
初始化,完成后多处package.json文件npm install webpack --save -dev
安装webpack
- 启动一个服务,先全局安装,
配置webpack
创建webpack.config.js
var path = require('path') var webpack = require('require') module.exports = { context: path.resolve(__dirname, './src'), extry: { app: './app.js' }. output: { path: path.resolve(__dirname, './dist') filename: 'bundle.js' } }
创建src app.js等文件
- 在package.json scripts里加入”start”: “webpack”,就可以在命令行执行start进行打包输出
- webpack进行代码压缩:
- 在config的exports中追加
plugins: [new webpack.optimize.UglifyJsPlugin()]
- 在config的exports中追加
- webpack的主要作用:
- 代码合并:合并commonjs的语法规范,否则前端无法识别
- 代码压缩:保证代码上线
上线回滚的流程
- 上线的基本流程
- 将测试完成的代码提交到git版本库的master分支
- 将当前服务器的代码全部打包并记录版本号,备份
- 将master分支的代码提交覆盖到线上服务器,生成新版本号
- 回滚的基本流程
- 将当前服务器的代码全部打包并记录版本号,备份
- 将备份的上一个版本号解压,覆盖到线上服务器,并生成新的版本号
- linux基本命令
- mkdir
- ls
- ll 列表形式的ls
- pwd
- cd
- cd ..
- rm -rf 文件夹名 //删除当前目录下所有文件
- vi a.js //创建并进入a.js
- i //insert
- : //最下行
- w //写
- q //退出
- cp a1 a2 //创建a2,把a1复制到a2
- mv a1 f1 //把a1移动到f1文件夹
- cat a1 //查看当前文件
- grep ‘2’ a.js //查找a.js中的2
运行环境
页面加载过程
- 加载资源的形式
- 输入url(或跳转页面)加载html
- 加载html中的静态资源
- 如
<script><img>
- 如
- 加载一个资源的过程
- 浏览器根据DNS服务器得到域名的IP地址
- 向这个IP的机器发送http请求
- 服务器收到、处理并返回http请求(图片,html js代码,)
- 浏览器得到返回的请求并渲染
- 浏览器渲染页面的过程
- 根据HTNL结构生成DOM树
- 根据CSS生成CSSOM(结构化处理)
- 将DOM和CSSOM整合成RenderTree(渲染树,每个节点都规定了样式)
- 根据RenderTree开始渲染和展示
- 遇到
<script>
时,会执行并阻塞渲染
- 题目
- 从输入url到得到html的详细过程
- 根据DNS得到域名IP-向该IP发送请求-服务器收到处理返回请求-浏览器得到返回内容
- window.onload和DOMCotentLoaded的区别
- onload:页面全部资源加载完,包括图片视频等才会执行
- CotentLoaded:DOM渲染完即可执行,图片还没有加载完
- 为什么把css文件放在head中?
- 因为渲染默认是顺序的,保证在渲染body时候浏览器已经知道对应的样式了
- 为什么把js放在body最下面?
- 不会阻塞之前body中html的渲染
- 保证script能拿到所有的html节点标签
- 从输入url到得到html的详细过程
性能优化
- 基本2点
- 多使用内存、缓存或者其他方法 -开源
- 减少CPU计算、减少网络 -节流
- 加载资源优化
- 静态资源的压缩合并
- 合并:将多个js文件合并成一个js
- 压缩:压缩体积
- 静态资源缓存
- 通过连接名称,名称不变的话,浏览器会加载之前同名的缓存
- 使用CDN让资源加载更快
- 不同区域的网络优化,上海转到上海的节点等等
- 使用SSR后端渲染,数据直接输出到HTML中(不同ajax请求数据)
- 静态资源的压缩合并
页面渲染优化
- CSS放前面,JS放后面
- 懒加载(图片懒加载,下拉加载更多/先用一张模糊的图片代替原图,要用的时候再加载) 什么时候用什么时候加载
- 减少DOM查询,对DOM查询做缓存
- 减少DOM操作,多个操作尽量合并在一个执行
- 先创建一个片段
frag=document.createDocumentFragment()
- 先创建一个片段
事件节流
- 间隔一段时间执行一次
如键盘输入,在ns内执行一次事件, 不停的输入,也会在一段时间后输出一次
//时间戳版 function throttle(fn, delay) { let previous = 0 return function (args) { let _args = args let _this = this let now = Date.now() if (now-previous > wait) { fn.call(_this, _args) previous = now } } }
事件防抖
- 超过一段时间不输入,执行一次
防止输入一个就输出一个这样的抖动情况,设置一个延迟,超过这个延迟不执行输入的情况下,才会执行输出。也就是输入一堆,停5ms不输入以后,才会输出
function debounce (fn, delay) { let timeout return function (args) { let _this = this let _args = args clearTimeout(timeout) timout = setTimeout(function (_args, _this) { fn.call(_this, _args) }, delay) } } //使用防抖 function print (content) { console.log(content) } let input = document.getElementById('text') let debounceInput = debounce(print, 100) input.addEventListener('keyup', function () { debounceAjax(e.target.innerHTML) })
尽早执行操作(DOMCotentLoaded)
安全性
- XSS跨站请求攻击
- 新浪博客写一篇文章,同时偷偷插入一段攻击代码
<script>
- 攻击代码中,获取查看者的cookie,发送到自己的服务器
- 新浪博客写一篇文章,同时偷偷插入一段攻击代码
- XSS预防
- 前端替换关键字,例如替换
<
为<;>
为> - 后端替换
- 前端替换关键字,例如替换
- XSRF跨站请求伪造
- 你已登录一个购物网站,正在浏览商品
- 付费接口是xxx.com/pay?id=100但是没有任何验证
- 你收到一封钓鱼邮件,隐藏着
<img src='xxx.com/pay?id=100'>
- 查看邮件的时候,就悄悄付费了
- XSRF预防
- 增加验证流程,如输入指纹、密码、短信验证码
- 问题
- 前端安全问题的场景有哪些
面试技巧
- 简历
- 简介明了,重点突出项目经历和解决方案
- 把个人博客放在简历中,并且定期维护更新博客
- 把个人的开源项目放在简历中,并维护开源项目
- 不能造假,要保证能力和经历上的造假
- 谈谈你的缺点
- 说一下最近正在学的东西,比如我对vue不是很了解,正在学vue.js
面试题
- window.onload和DOMCotentLoaded的区别
- onload事件触发:页面上所有dom,样式表,脚本,图片,flash都已经加载完;DOMCotentLoaded:仅dom加载完
- 如何理解JSON
- 是一个JS对象,有两个API:
JSON.stringify(obj)//将js的对象转换成json字符串
JSON.parse('{"a":5}')
//json字符串转js对象
- 是一个数据格式
- 是一个JS对象,有两个API:
- js有哪些内置函数
- Object
- Array
- Boolean
- Number
- String
- Function(以上为构造函数)
- Date
- RegExp
- Error
- new一个vue对象发生了什么?
- 执行this._init()方法,初始化对象:
- 合并配置options
- 初始化生命周期
- 初始化事件中心
- 初始化渲染
- 初始化data,props,computed,watcher等
- 初始化完成,检查如果有el属性,就调用vm.$mount方法挂载
- 执行this._init()方法,初始化对象:
promise
一种异步解决方案,类似一个容器,包括未来会执行的任务
.then()
参数1为resolve的内容,参数2(可以不要)为reject的内容
.catch()
用于resolve有错误的情况,一般用在.then的最后
.finally()
用于不管promise最后状态如何都执行的操作
.all()
用于将多个promise包装成一个const p = Promise.all([p1, p2, p3]);
- 必须等三个都resolve,p才resolve,而有一个reject p就reject
- 场景:几个任务时间不一样,需要等全部完成才执行下一个任务
.race()
Promise.race方法同样是将多个 Promise 实例,包装成一个新的 Promise 实例。const p = Promise.race([p1, p2, p3])
- 只要有一个resolve了,就算完成
- 场景:把异步操作和定时器绑定,如果定时到了异步操作还没完成就报错
.resolve()
将对象转换为promise对象,状态为resolvelet jsPromise = Promise.resolve(para)
- param:
- promise对象,直接返回不做修改
- thenable对象:有
then: function(resolve, reject){resolve()}
的对象,直接封装,立即执行then - 普通对象:直接封装,状态为resolve
.reject()
将对象转换为promise对象,状态为reject
.try()
模拟try代码块