React/TypeScript扩展运算符复制类实例引发compareTo方法异常原因
扩展运算符复制类实例后箭头方法this绑定异常的原因分析
先看你的代码:
定义的Item类:
class Item { id:number; constructor(id:number) { this.id = id; } compareTo = (i2:Item) => { return this.id === i2.id; } }
复制实例后的测试代码:
const selectedObj = { item: new Item(1) }; let item:Item = {...selectedObj.item}; console.log(item.id) // 1 console.log(item.compareTo(item)) //true item.id = 123; console.log(item.id) //123 console.log(item.compareTo(item)) //false
问题根源
核心原因是箭头函数作为类属性时,this在定义阶段就绑定到了原实例,和复制后的新对象无关:
- 用
{...selectedObj.item}做浅拷贝时,只是把原实例的可枚举属性(包括id和compareTo箭头函数)复制到了一个新的普通对象上(这个新对象并不是Item类的实例,只是结构类似的对象)。 compareTo作为箭头函数,它的this在原实例new Item(1)创建时就已经固定指向原实例,所以不管你怎么修改新对象的id,调用compareTo时,函数内部的this.id始终是原实例的id=1。- 修改新对象的
id为123后,调用compareTo(item)时,this.id是原实例的1,i2.id是新对象的123,自然返回false。
解决方法
把compareTo改成类的原型方法,不要用箭头函数定义:
class Item { id: number; constructor(id: number) { this.id = id; } // 普通原型方法,this在调用时绑定到当前对象 compareTo(i2: Item) { return this.id === i2.id; } }
这样修改后,compareTo挂载在Item.prototype上,调用item.compareTo(item)时,this会自动绑定到调用方法的对象(复制后的新对象),此时this.id就是新对象的当前值,对比结果符合预期。
另外要注意:扩展运算符{...}复制类实例时不会拷贝原型上的方法,如果你需要新对象保留Item类的所有原型方法,更规范的做法是创建类的新实例,比如:
let item: Item = new Item(selectedObj.item.id);
或者在类里添加一个拷贝方法:
class Item { id: number; constructor(id: number) { this.id = id; } compareTo(i2: Item) { return this.id === i2.id; } copy(): Item { return new Item(this.id); } } // 使用拷贝方法 let item: Item = selectedObj.item.copy();
内容的提问来源于stack exchange,提问作者Marc
相关产品推荐
相关产品推荐

