前几天在写一个后盾我的项目的时候应用object.assgin时呈现了一个很奇怪的bug,特写了一个简略的demo探索一下。demo为一个根底表单:
后端数据中只有name和喜好有值。
此时依据后端数据将表单中的数据赋值:this.personData = res.data.userTableData
成果非常的合乎预期,轻易点点也没有什么其余的问题:
但如果用上面这种形式对表单数据进行赋值:Object.assign(this.personData, res.data.userTableData)
奇怪的景象产生了,刷新后表单没有初始数值,而且表单的批改不失效:
此时批改静止栏的值后发现前两栏的数据终于更新了,然而前两栏的数据仍然是不能做任何的间接批改,只有静止一栏的数据批改后,前两栏数据之前做过的批改才会显示进去。让人不禁想问到底产生了什么。
为此我查问了object.assgin相干的代码,发现这篇文章:
Object.myAssign = function (target, ...src) { for (let i = 0; i < src.length; i++) { if (src[i] !== null || src[i] !== undefined) { // 过滤掉源对象为null和undefined的状况 for (let key in src[i]) { // in运算符会查找原型对象上的可枚举属性,所以须要通过Object.prototype.hasOwnProperty办法过滤掉对象原型对象上的属性 if (src[i].hasOwnProperty(key)) { target[key] = src[i][key] } } } } return target}
要害代码:target[key] = src[i][key]
到这里开始问题就初现端倪了,我又找到了上面这篇文章
要害局部:
person.name = {name: 'tom'} =>触发了set
person.name =>{name: "tom"}
person.name.name = 123123
=>没有打印出任何信息,阐明批改name的属性值并没有触发set办法。
person.name.sex = 333
=>没有打印出任何信息,阐明增加name的属性值并没有触发set办法。 delete person.name.name =>没有打印出任何信息,阐明删除name的属性值并没有触发set办法。
Object.defineProperty(person.name, 'name', {value: 4444}) =>没有打印出任何信息,阐明Object.defineProperty也没有触发set办法。
我直呼好家伙,原来对象的双向数据绑定失效条件竟然如此刻薄,object.assgin的赋值办法没有触发到set函数,天然也不会告诉到调用其值的对象上,直到在表单中给静止栏赋值时this.personData
的set被触发,之前的所有表单的数据变动才被展现进去。
这时第二个问题呈现了,为什么在批改静止一栏的数据时会又这么反常的景象?
我认为是当间接批改对象里的值时,仅仅是扭转了指向栈数据的指针指向,对于双向数据绑定并未产生无效影响。所以此时批改前两栏的数据时尽管this.personData
里的属性的指针指向被批改了,但批改值在双向数据绑定中的指针指向还是之前的地址。这也解释了为什么在批改静止一栏的值后之前做过的变动又会展现进去,因为this.personData
的值的确被扭转了,但你之后无论怎么扭转前两栏的数据,都是不会有任何变动展现进去的。
援用的相干文章地址:
- https://segmentfault.com/a/11...
- https://www.cnblogs.com/yanze...