vue2响应式原理
Object.defineProperty()
// Object.defineProperty();
// 有三个属性 (obj,prop,descriptor) (对象,属性,描述项集合)
function defineProperty() {
var _obj = {};
//1.声明一个属性a
// Object.defineProperty(_obj, "a", {
// value: 1, //设置默认值
// });
//2.声明多个属性
Object.defineProperties(_obj, {
a: {
value: 1,
},
b: {
value: 2,
},
});
return _obj;
}
var obj = defineProperty();
obj.a = 5
console.log(obj); //{a: 1, b: 2} //属性值不可以修改
for (let k in obj){
console.log(k + ':' + obj[k]); //属性值不可枚举
}
delete obj.a //属性值不可以删除
//总结:使用Object.defineProperties定义的属性不可以修改 删除 枚举
?? 如何可以进行修改
function defineProperty() {
var _obj = {};
Object.defineProperties(_obj, {
a: {
value: 1,
writable: true, //a属性可以进行修改
enumerable: true, //a属性变为可枚举
configurable: true, //a属性可以进行操作(删除)
},
b: {
value: 2,
},
});
return _obj;
}
var obj = defineProperty();
obj.a = 5;
console.log(obj); //{a: 5, b: 2}
for (let k in obj) {
console.log(k + ":" + obj[k]); //{a:5}
}
delete obj.a;
console.log(obj); //{b:2}
function defineProperty() {
var _obj = {};
var a = 1;
//每一个属性定义的时候 getter 和 setter都是存在的
Object.defineProperties(_obj, {
a: {
get() {},
set(newVal) {
a = newVal;
var P = document.getElementsByTagName("p")[0];
P.innerHTML = a;
},
},
b: {},
});
return _obj;
}
var obj = defineProperty();
obj.a = 2 //会触发setter方法
触发getter setter 方法 -->每一个属性定义的时候 getter 和 setter都是存在的
function defineProperty() {
var _obj = {};
var a = 1;
//每一个属性定义的时候 getter 和 setter都是存在的
Object.defineProperties(_obj, {
a: {
get() {
return '"a" value is ' + a + ".";
},
set(newVal) {
console.log(
'The value "a" has been designed a new value ' + newVal + ""
);
},
},
b: {},
});
return _obj;
}
var obj = defineProperty();
console.log(obj.a); //触发get方法 "a" value is 1.
obj.a = 2; //会触发setter方法 The value "a" has been designed a new value 2
以上触发getter setter方法的过程就是 数据劫持,数据劫持其实就是将对象中属性变成可配置
vue3响应式原理
Proxy
// Proxy ES6 中的构造函数
function Proxy() {}
var proxy = new Proxy();
// defineProperty 劫持数据 -> 给对象进行扩展 -> 对对象中的属性进行设置
var obj = new Proxy(target, handler);
//target 目标对象 你要进行处理的对象
//handler 容器 里面放无数可以处理对象属性的方法
//自定义对象属性的获取,赋值,枚举,函数调用等功能
var target = {
a: 1,
b: 2,
};
var proxy = new Proxy(target, {
get(target, prop) {
return "this is property value" + target[prop];
},
set(target, prop, value) {
target[prop] = value;
console.log(target[prop]); //3
},
});
console.log(proxy.a); //此时触发get方法 this is property value 1
proxy.b = 3 //此时触发set方法
let arr = [
{ name: "小王", age: 18 },
{ name: "小红", age: 20 },
{ name: "小刘", age: 14 },
];
let persons = new Proxy(arr, {
get(arr, prop) {
return arr[prop];
},
set(arr, prop, value) {
arr[prop] = value;
},
});
console.log(persons[0]); // { name: "小王", age: 18 },
persons[1] = { name: "小黑", age: 30 };
console.log(persons); //{0: {name: "小王", age: 18 }, 1: {name: "小黑", age: 30}, 2: {name: "小刘", age: 14}}
var obj = { a: 1, b: 2 };
// 1.获取原型 [[GetPrototypeOf]]
var proto = Object.getPrototypeOf(obj);
console.log(proto);
console.log(obj.__proto__);
console.log(Object.prototype); //以上三种输出结果是一样的
//设置原型 [[SetPrototypeOf]]
Object.setPrototypeOf(obj, { c: 3, d: 4 });
console.log(obj); //输出见下图
//3.获取对象的可扩展性 [[IsExtensible]]
var extensible = Object.isExtensible(obj);
console.log(extensible); //true
Object.freeze(obj); //将对象进行冻结,使对象不具有可扩展性(不可删除,不可修改,不可写,可读)
var extensible2 = Object.isExtensible(obj);
console.log(extensible2); //false
//4.获取自有属性 [[GetOwnProperty]]
//5.禁止扩展对象 [[PreventExtensions]]
//6.拦截对象操作 [[DefineOwnProperty]]
//7.判断是否是自身属性 [[hasOwnProperty]]
//8. [[Get]]
console.log("a" in obj); //true
console.log(obj.a); //1
//9.[[set]]
obj.a = 3;
obj["b"] = 4;
//10.[[Delete]]
delete obj.a;
//11.[[Enumerate]]
for (var k in obj) {
console.log(obj[k]);
}
//12.获取键集合 [[OwnPropertyKeys]]