响应式原理
认识Object.prototype.constructor
返回创建实例对象的 Object 构造函数的引用。注意,此属性的值是对函数本身的引用,而不是一个包含函数名称的字符串。对原始类型来说,如1,true和"test",该值只可读。
var o = {}; o.constructor === Object; // true var o = new Object; o.constructor === Object; // true var a = []; a.constructor === Array; // true var a = new Array; a.constructor === Array // true var n = new Number(3); n.constructor === Number; // true
对象的构造函数
function Tree(name) { this.name = name; } var theTree = new Tree("Redwood"); console.log( "theTree.constructor is " + theTree.constructor );
改变constructor
obj instanceof Object 检测Object.prototype是否存在于参数obj的原型链上。
function Type() {}; var types = [ new Array, [], new Boolean, true, // remains unchanged new Date, new Error, new Function, function() {}, Math, new Number, 1, // remains unchanged new Object, {}, new RegExp, /(?:)/, new String, "test" // remains unchanged ]; for (var i = 0; i < types.length; i++) { types[i].constructor = Type; types[i] = [types[i].constructor, types[i] instanceof Type, types[i].toString()]; }; console.log(types.join("\n"));
输出:
get、set
obj.__defineGetter__(prop, func)
prop
一个字符串,表示指定的属性名。
func
一个函数,当 prop 属性的值被读取时自动被调用。
// 请注意,该方法是非标准的: var o = {}; o.__defineGetter__('gimmeFive', function() { return 5; }); console.log(o.gimmeFive); // 5 // 请尽可能使用下面的两种推荐方式来代替: // 1. 在对象字面量中使用 get 语法 var o = { get gimmeFive() { return 5; } }; console.log(o.gimmeFive); // 5 // 2. 使用 Object.defineProperty 方法 var o = {}; Object.defineProperty(o, 'gimmeFive', { get: function() { return 5; } }); console.log(o.gimmeFive); // 5
obj.__defineSetter__(prop, fun)
prop
一个字符串,表示指定的属性名。
fun
一个函数,当试图去为 sprop 属性赋值时被调用。通常你要给这个函数指定一个参数:
Object.defineProperty()
JavaScript 对象传入 Vue 实例作为 data 选项,Vue 将遍历此对象所有的 property,并使用 Object.defineProperty 把这些 property 全部转为 getter/setter。Object.defineProperty 是 ES5 中一个无法 shim 的特性。 getter/setter 对用户来说是不可见的,但是在内部它们让 Vue 能够追踪依赖,在 property 被访问和修改时通知变更。
每个组件实例都对应一个 watcher 实例,它会在组件渲染的过程中把“接触”过的数据 property 记录为依赖。之后当依赖项的 setter 触发时,会通知 watcher,从而使它关联的组件重新渲染。
MVVM设计模式(响应式原理)
View和Model之间并没有直接的联系,而是通过ViewMode进行交互,ViewModel通过双向数据绑定把View层和Model层连接了起来
const data = {}; let name = "张三"; Object.defineProperty(data, 'name', { get: function() { console.log('触发get') return name }, set: function(newVal) { console.log('触发set') name = newVal } }) //测试 console.log(data.name) // 触发get 张三 data.name = '李四' // 触发set