Skip to main content

Vue2与Vue3的『响应式原理』

· 4 min read
LIU

一个是定义属性,一个是代理

Object.defineProperty()

define 定义 property 属性

(obj , prop , descriptor)
description 叙述、表述
descript 动词
descriptor 描述项集合

function defineProperty(){
let obj = {};
//单个
Object.defineProperty(obj,'a',{
value:1,
writable:true, //是否可修改
enumerable:true, //是否可枚举
configurable:true, //是否可配置(可删除)
// ↑↓ 不能同时使用,互斥
get(){
return a //需要return
},
set(newVal){
a = newVal
}
})
//多个
Object.defineProperties(obj,{
a:{
value:1
},
b:{
value:2
}
})
return obj
}
let i = defineProperty();
console.log(i) // 单个:{a:1} , 多个:{a:1,b:2}

//默认不可修改、枚举、删除 , 需要通过对应属性设置成true

//数据劫持 指借助getter和setter,阻拦正常的输入和输出 改变之前的访问逻辑

Proxy

ES6的构造函数

let obj = new Proxy(target,handler);
//target 目标对象 你要进行处理的对象
//handler 容器 可以处理对象属性的方法
//自定义对象属性的获取、赋值、枚举、函数调用等功能

let target = {
a:1,
b:2
}
// 返回 代理对象
let proxy = new Proxy(target,{
get(target,prop){
return target[prop]
},
set(target,prop,newVal){
target[prop] = newVal
},
has(){},
deleteProperty(){},
})
console.log(proxy.a)
proxy.b = 3
//数组也同理

Proxy 可以重写handler里的方法进行拦截(代理 操作对象)

函数式操作 Reflect

let obj = {a:1,b:2}
let proxy = new Proxy(obj,{
get(target,prop){
return Reflect.get(target,prop)
}
set(target,prop,value){
Reflect.set(target,prop,value)
}
})

Reflect.has(obj,'a'); //true

image-213402359

Reflect是内置的全局对象,保存静态方法,不需要实例化

类似像Math

延伸

1.获取原型 getPrototypeOf

let obj = {a:1,b:2};
let proto = Object.getPrototypeOf(obj);
console.log(proto);
console.log(obj.__proto__);
console.log(Object.prototype);

image-115817052

2.设置原型 getPrototypeOf

Object.setPrototypeOf

let obj = {a:1,b:2};
Object.setPrototypeOf(obj,{c:3,d:4})
// obj.__proto__
// Object.prototype
console.log(obj);

image-144340313

3.获取对象的可扩展性 isExtensible

Object.isExtensible Object.freeze Object.seal

let obj = {a:1,b:2}
let extensible = Object.isExtensible(obj);
console.log(extensible); //true
Object.freeze(obj); //冻结对象,不可修改(新增),不可删除,不可写,可读
let extensible2 = Object.isExtensible(obj);
console.log(extensible); //false
let obj = {a:1,b:2}
Object.seal(obj); //封闭对象
obj.c = 3 //不可修改(新增)
delete obj.c //不可删除
obj.b = 3 //可写、可读

4.获取自由属性 getOwnProperty

Object.getOwnProperty

let obj = {a:1,b:2}
Object.setPrototypeOf(obj,{c:3,d:4})
console.log(Object.getOwnPropertyNames(obj));// ["a","b"]

5.禁止扩展对象 preventExtenstions

Object.preventExtenstions

let obj = {a:1,b:2}
Object.preventExtensions(obj);
obj.c = 3 //不可新增
console.log(obj); // {a:1,b:2}
delete obj.a //可删除

6.拦截对象操作 defineProperty

Object.defineProperty

Object.defineProperty()

7.判断是否自身属性 hasOwnProperty

Object.hasOwnProperty

let obj = {a:1,b:2}
Object.hasOwnProperty('a') //true
//深拷贝的时候用到

8.get

let obj = {a:1,b:2}
console.log('a' in obj) //true
console.log(obj.a) //1
//底层都是通过get方法实现

9.set

let obj = {a:1,b:2}
obj.a = 3
console.log(obj) //{a:3,b:2}

10.delete

let obj = {a:1,b:2}
delete obj.a
console.log(obj) //{b:2}

11.枚举 enumerate

let obj = {a:1,b:2}
for(let i in obj){
console.log(obj[i]) //1,2
}

12.获取键集合 OwnPropertyKeys

let obj = {a:1,b:2}
console.log(Object.keys(obj)) //['a','b']

Object.setPrototypeOf(obj,{c:3,d:4});
console.log(Object.keys(obj)) //['a','b']

13.函数调用

function test(){}
test()
obj.test = function(){}
obj.test()

14.new

function Test(){}
new Test()

在ES6标准当中,任何的语法和对象相关的内建函数方法都是基于这14种内部方法构建出来的