TS有两个对象,便利B对象的属性,如果A对象有这个属性,就把B的值更新到A对象。
自行实现
在TypeScript中,可以通过遍历一个对象的属性并检查另一个对象是否具有相同的属性来实现这个功能。如果有相同的属性,则将其值从一个对象更新到另一个对象。以下是一个示例,展示了如何实现这种属性更新:
假设有两个对象 A 和 B:
interface A {
[key: string]: any;
}
interface B {
[key: string]: any;
}
const a: A = {
name: 'Alice',
age: 30,
city: 'New York'
};
const b: B = {
age: 35,
city: 'Los Angeles',
country: 'USA'
};
我们希望遍历对象 B 的属性,如果对象 A 也有这个属性,就将对象 B 的值更新到对象 A 中。可以这样实现:
function updateObjectProperties<T extends object, U extends object>(target: T, source: U): void {
for (const key in source) {
if (source.hasOwnProperty(key) && target.hasOwnProperty(key)) {
target[key] = source[key];
}
}
}
// 更新对象 `a` 的属性
updateObjectProperties(a, b);
console.log(a);
// 输出结果: { name: 'Alice', age: 35, city: 'Los Angeles' }
在上面的代码中:
定义了一个泛型函数 updateObjectProperties,它接受两个对象 target 和 source。
使用 for...in 循环遍历 source 对象的属性。
对每个属性,检查 target 对象是否也有相同的属性。
如果 target 对象有这个属性,将 source 对象的属性值赋值给 target 对象的相应属性。
这样,所有在 source 对象中存在且在 target 对象中也存在的属性都会被更新。
上面这种方法会有红线报错提示
1. 报错原因:使用hasOwnProperty直接从source和target对象调用,违反了ESLint的no-prototype-builtins规则。该规则建议不要直接访问对象原型方法,以避免潜在的安全问题和更好的代码可读性。
2. 修复建议:应使用Object.prototype.hasOwnProperty.call(object, propertyName)的方式来调用hasOwnProperty方法,以避免直接从对象上调用可能导致的问题。
3. 修复代码:
if (Object.prototype.hasOwnProperty.call(source, key) && Object.prototype.hasOwnProperty.call(target, key)) {
这样修复后,代码将不再违反no-prototype-builtins规则,同时也能确保hasOwnProperty方法的安全调用。
代码如下:
修复后依然会有一个报错:
1. 报错原因:该错误表明在使用TypeScript时,尝试用一个类型的某些键(可能为字符串类型)去索引另一个类型,但TypeScript编译器认为这种操作不安全,因为索引类型“T”可能不包含那些键。
2. 修复建议:确保target对象确实包含将要被赋值的键。可以通过泛型约束或者类型断言来解决这个问题。如果确定source[key]的类型与target[key]兼容,也可以在赋值前进行类型断言。
export function updateObjectPropertiesV3<T extends object, U extends object>(target: T, source: U): void {
for (const key in source) {
if (Object.prototype.hasOwnProperty.call(source, key) && Object.prototype.hasOwnProperty.call(target, key)) {
// target[key] = source[key];
(target as any)[key] = (source as any)[key];
}
}
}
借助于lodash封装 【建议使用】
符合ts规范,不会有报错提示
// updateObjectProperties.ts
import _ from 'lodash'
interface AnyObject {
[key: string]: any
}
export function updateObjectProperties(target: AnyObject, source: AnyObject): void {
_.forEach(source, (value, key) => {
if (_.has(target, key)) {
_.set(target, key, value)
}
})
}
其他延申>属性判断hasOwnProperty
和in
的区别
现在有连段代码:
export function updateObjectPropertiesV3<T extends object, U extends object>(target: T, source: U): void {
for (const key in source) {
if (Object.prototype.hasOwnProperty.call(source, key) && Object.prototype.hasOwnProperty.call(target, key)) {
// target[key] = source[key];
(target as any)[key] = (source as any)[key];
}
}
}
和
export function updateObjectPropertiesV3<T extends object, U extends object>(target: T, source: U): void {
for (const key in source) {
if (key in target) {
(target as any)[key] = (source as any)[key];
}
}
}
这两段代码的区别如下:
两段代码的主要区别在于使用 Object.prototype.hasOwnProperty.call 来检查属性是否存在于对象自身,而不是使用 in 操作符。hasOwnProperty 方法更为严格,因为它只检查对象自身的属性,而 in 操作符还会检查原型链上的属性。
在实际应用中,使用 hasOwnProperty 更为安全和推荐,因为它可以避免原型链上意外的属性干扰。
hasOwnProperty优点解释
1. 安全性:
- Object.prototype.hasOwnProperty.call(source, key) 确保 key 是 source 对象自身的属性,而不是从原型链继承的。
- Object.prototype.hasOwnProperty.call(target, key) 确保 key 是 target 对象自身的属性,避免修改到原型链上的属性。
2. 可读性和可维护性:
- 使用 hasOwnProperty 明确表明你只关心对象自身的属性,这使代码更易读和理解。
3. 避免潜在的错误:
- in 操作符会检查整个原型链上的属性,可能导致意外修改继承的属性,使用 hasOwnProperty 可以避免这种情况。