vue

125 阅读3分钟

1、什么是虚拟DOM?

虚拟DOM的本质是JavaScript对象,是对真实DOM的描述,用一个js对象来描述一个DOM节点。 在监听到数据发生变化后会生成虚拟DOM节点,会与上次虚拟DOM节点进行对比,找到差异部分,渲染到真实DOM节点上面更新视图。虚拟DOM可以提高页面的渲染的效率,减轻对节点的操作。可以实现跨平台。不需要手动操作DOM。

2、原型和原型链

在js中,每个对象都会有一个[[prototype]]属性,这个属性就是对象的原型,属性的值是也对象也有自己的原型。在访问对象的属性时,会先在对象本身查找,没找到就会去对象的原型中查找,然后再到原型对象的原型中查找,这样形成的链式结构叫做原型链。原型链的最后是Object的原型对象的[[prototype]]属性,值为null。对象只有隐式原型(proto),函数有显式原型(prototype)。

2.1、继承

方案一:将父类的显式原型(prototype)赋值给子类的显式原型(prototype)。

缺点:子类添加的方法会影响父类。

function Persion() {}
function Student() {}
Student.prototype = Persion.prototype

方案二:通过new操作符操作父类创建一个新对象,将新对象赋值给子类的显式原型(prototype)。

缺点:子类继承过来的方法无法在原型中显示

function Persion() {}
function Student() {}
const p = new Persion()
Student.prototype = p

方案三:让子类的显式原型的隐式原型指向父类的显式原型

缺点: __proto__存在兼容问题。

function Persion() {}
function Student() {}
Student.prototype.__proto__ = Persion.prototype

方案四:通过new操作符操作父类创建一个新对象,将新对象赋值给子类的显式原型(prototype),并且在子类的内部借用构造函数的方法实现属性的继承。

缺点: 父类会调用两次。

function Persion() {}
function Student() {
    Persion.call(this)
}
const p = new Persion()
Student.prototype = p

方案五:寄生组合式继承

1、先创建一个中间函数,函数接受父类的显式原型
2、函数中创建新的函数,并且将父类的显式原型赋值给新函数的显式原型,返回该函数的类(new Foo())
3、将返回值赋值给子类的显示原型,并且在子类的constructor中将子类赋值给它(因为函数的显式原型的constructor指向行数本身)

function createobject(o) {
    function F() {}
    F.prototype = o
    return new F()
}
function inherit(subtype, supertype) {
    Subtype.prototype=createobject(supertype.prototype)
    object.defineProperty(subtype.prototype"constructor",{
        enumerable: false,
        configurable: true,
        writable: true,
        value: Subtype
    })
}

function Person() {}
function student() {
    Person.ca11(this)
}
inherit(student, Person)

3、说说对GO/AO/VO的理解

GO:js代码在执行前会先在堆内存中创建一个全局对象(GO),用来存放一些定义好的变量方法等包含Date,Array,String等等。同时有一个window指向自己,并且在语法分析的时候也会把定义的变量函数存放在GO中只是变量的初始值式undefined。

AO:函数在执行前会先在堆内存中创建一个AO对象,里面存放着arguments对应函数的形参以及函数定义的变量初始值为undefined。

VO:变量环境,在执行函数时会创建函数的执行上下文栈,函数的VO指向AO,全局函数的执行上下文指向GO。每一个执行上下文都会关联一个VO。

4、vue.$set原和数组的响应式

$set接受三个值分别是目标对象,设置的key和value。调用时会判断传入的目标对象是否是undefined或者null,是直接抛出异常。然后会判断是否是数组是直接用splice进行赋值,是对象就通过defineReactive方法 将数组转化成get和set方式添加数据。

数组的响应式首先拿到有拿到数组的原型,通过对push,pop,shift,unshift,splice,sort,reverse这七个方法进行劫持和重写,遍历添加响应式。