前端笔记--JS高级
ES6
模块化
- 语法(详见上一篇)
import export(注意有无default的区别) - 环境
使用babel编译ES6语法,模块化工具使用webpack和rollup
Class
基本语法
//构造函数
function MathHandle(x,y) {
this.x = x;
this.y = y;
}
MathHandle.prototype.add = function () {
return this.x + this.y;
}
const m = new MathHandle(1,2);
alert(m.add())
//class
class MathHandle {
constructor(x,y){
this.x = x;
this.y = y;
}
add(){
return this.x + this.y
}
}
const m = new MathHandle(1,2);
alert(m.add())
class的本质是一个语法糖,是构造函数的另一种写法,只是这种写法更偏向于传统的面向对象语言的语法。
typeof MathHandle //function
class的数据类型就是函数
MathHandle === MathHandle.prototype.constructor
类本身就指向构造函数
m._proto_ === MathHandle.prototype //true
实例对象的__proto__属性值也指向类的prototype属性值
继承
Class之间可以通过extends关键字实现继承,子类必须在constructor方法中调用super方法,表示父类的构造函数,否则新建实例时会报错。这是因为子类没有自己的this对象,而是继承父类的this对象,然后对其进行加工。如果不调用super方法,子类就得不到this对象。
//使用构造函数实现继承
function Animal(name){
this.name = name;
this.eat = function () {
console.log(this.name+'eat')
}
}
function Dog(name) {
this.name = name;
this.bark = function () {
console.log(this.name+'汪汪汪!')
}
}
Dog.prototype = new Animal(name)
const hashiqi = new Dog('哈士奇')
hashiqi.bark()
hashiqi.eat()
//class实现继承
class Animal {
constructor(name){
this.name = name
}
eat(){
console.log(this.name+'eat')
}
}
class Dog extends Animal {
constructor(name){
super(name);
this.name = name
}
bark(){
console.log(this.name+'汪汪汪')
}
}
const hashiqi = new Dog('哈士奇')
hashiqi.bark()
hashiqi.eat()
Promise
Promise详解
Promise 是异步编程的一种解决方案,其实是一个构造函数,自己身上有all、reject、resolve这几个方法,原型上有then、catch等方法。
Promise对象有以下两个特点:
(1)对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态,pending(进行中),fulfilled(已成功),rejected(已失败)。只有异步操作的结果能决定当前当前是哪一种状态,任何其他操作都无法改变这个状态。
(2)一旦状态改变就不会再变,任何时候都可以得到这个结果。Promise对象状态的改变只有两种可能,一种是从pending变为fulfilled,一种是从pending变成rejected,只要这两种情况发生,状态就凝固了,不会在改变了,会一直保持这个结果,这时就称为resolved(已定型)。
注意:当我们new了一个Promise对象,但并没有调用它,传进去的函数也会执行,所以我们用Promise的时候一般是包在一个函数中,在需要的时候去运行这个函数。
- resolve方法的作用是,将Promise对象的状态从“进行中”变为“已成功”,在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;
- reject方法的作用是,将Promise对象的状态从“进行中”变成“已失败”,在异步操作失败时调用,并将异步操作的报错信息,作为参数传递出去;
- Promise实例生成后,使用then方法分别指定成功和失败的回调函数
- catch方法是用来捕获异常的,与try catch类似,也就是和then方法中接收的第二参数reject的回调是一样的,它还有另外一个作用:在执行resolve的回调(也就是上面then中的第一个参数)时,如果抛出异常了,那么并不会报错卡死js,而是会进到这个catch方法中。
- Promise.all方法,该方法提供了并行执行异步操作的能力,并且在所有异步操作执行完后并且执行结果都是成功的时候才执行回调。all接收一个数组参数,这组参数为需要执行异步操作的所有方法。
- Promise.race方法,与all方法不同的是谁先执行完成就先执行回调。先执行完的不管是进行了race的成功回调还是失败回调,其余的将不会再进入race的任何回调
async/await
并不与Promise冲突,是Promise的一个扩展、优化。写法上完全是同步的写法,没有回调函数。(需要引入polyfill.js编译)
- await只能在用async标识的函数内部使用
- await关键字后面跟Promise对象实例
- await是异步等待的意思,等promise实例对象状态变为resolved的时候,再顺序执行后面的代码
- await只关心异步的成功结果,不关心不处理失败的信息,可以将代码放在try catch结构中捕获异常
其他常用功能
- let/const
- 模板字符串
传统的javascript,输出模板通常是这样写的
var name = "Jack",age = 20,html = ""
html+='<div>'
html+='<p>'+name+'</p>'
html+='<p>'+age+'</p>'
html+='</div>'
ES6写法
const name = "Jack",age = 20
const html = `
<div>
<p>${name}<p>
<p>${age}</p>
</div>
模板字符串使用反引号(`)包裹起来,如果需要嵌入变量,将变量名写在${}之中
- 解构赋值
通过解构赋值,可以将对象的属性或数组的值取出来,赋值给其他变量。
赋值的两边具有相同的结构,就可以正确取出数组的元素或对象里面的属性值
注意:解构对象时,如果进行无申明赋值,赋值语句要用()包起来 - 块级作用域
- 函数默认参数
允许为函数的参数设置默认值,直接写在参数定义的后面。 - 扩展运算符
... 可以将一个数组转为用逗号分隔的参数序列 - 箭头函数
适用于那些本来需要匿名函数的地方。把function变成了箭头,语法是参数,箭头,函数体,当只有一个参数时,圆括号是可以省略的,多个参数或没有参数都不能省略圆括号。当箭头函数的函数体只有一条return语句时,可以省略return关键字和方法体的花括号。箭头函数不会创建自己的this,它只会从自己的作用域链的上一层继承this。
异步
- js单线程
原因:为了避免DOM渲染的冲突 - event-loop
主线程从"任务队列"中读取执行事件,这个过程是循环不断的,这个机制被称为事件循环。 - JavaScript的运行机制
(1)所有同步任务都在主线程上执行
(2)异步任务先放到异步队列中,(如果是setTimeout不设置延时,立刻放到异步队列中,如果设置了延时时间,延时结束后放到异步队列中,ajax请求加载完成后再放到异步队列中)
(3)主线程任务执行完成后,看异步队列里有没有等待执行的任务,如果有就拿到主线程中执行
(4)不断重复第三步操作
Virtual Dom 虚拟DOM
什么是虚拟DOM
用JS模拟DOM结构,为了减少DOM操作,提高效率
snabbdom
Snabbdom 是一个虚拟 DOM 库
核心函数
- h函数 虚拟一个DOM结构
h('元素选择器',{属性},[子元素]) //元素节点的子元素
h('div#container.two.classes', {on: {click: someFn}}, [
h('span', {style: {fontWeight: 'bold'}}, 'This is bold'),
' and this is just normal text',
h('a', {props: {href: '/foo'}}, 'I\'ll take you places!')
])
h('元素选择器',{属性},'') //文本节点的子元素
h('span', {style: {fontWeight: 'normal', fontStyle: 'italic'}}, 'This is now italic type')
- patch函数 渲染DOM
1.初次渲染,把vnode的内容全部渲染到container容器中
patch(container,vnode)
2.再次渲染,将新的vnode跟旧的vnode进行对比,只重新渲染变化的部分
patch(vnode,newVnode)
Diff算法
是Linux的基础命令,git中也使用git diff 文件名 来查看修改了文件的什么内容
虚拟DOM中应用diff算法是为了找出需要更新的节点
MVVM
从Jquery到框架的(VUE)的区别
- 数据与视图的分离,解耦(开放封闭原则)
- 以数据驱动视图,只关心数据的变化,DOM操作被封装
如何理解MVVM

1.MVVM是在后端MVC上的微创新,M代表数据模型,V代表试图,VM(ViewModel)是连接视图和数据的一个桥梁
2.view通过ViewModel的事件监听来操作model,model通过ViewModel的数据绑定来操作view
3.mvvm数据跟视图是分离的,通过数据来驱动视图,开发者只需要关心数据变化,DOM操作被封装了
vue三要素
- 响应式:vue如何监听到data每个属性的变化
Object.defineProperty()
将data、method的属性代理到vm上
![]()
- 模板解析引擎:vue的模板如何被解析,指令如何处理
模板:字符串,有逻辑,嵌入JS变量
模板必须转换为JS代码(有逻辑、有JS变量、渲染html)
render函数中的vm._c函数与snabbdom中的h函数类似
render函数执行返回vnode - 渲染:vue的模板如何渲染成html,以及渲染过程
vm._update函数
vue的整个实现流程
1.解析模板成render函数
2.响应式开始监听
3.首次渲染,显示页面,并绑定依赖
4.data属性变化,触发rerender

浙公网安备 33010602011771号