Typescript 对象赋值后相等吗

在编程中,对象赋值是一种常见的操作。在TypeScript中,对象是通过引用(Reference)来传递的。当我们将一个对象赋值给另一个变量时,实际上是将对象的引用地址赋给了新变量,而不是将对象的内容复制一份。因此,在比较两个对象时,我们需要注意对象的引用关系。
什么是对象赋值
首先,让我们来看一个简单的示例:
let obj1 = { name: "Alice", age: 30 };
let obj2 = obj1;
console.log(obj1 === obj2); // true
在上面的代码中,我们定义了一个名为obj1的对象,包含了name和age两个属性。然后我们将obj1赋值给了obj2。最后我们比较了obj1和obj2是否相等,结果为true。这是因为obj1和obj2都指向了同一个内存地址的对象。
浅拷贝和深拷贝
在实际开发中,我们经常需要对对象进行复制操作,以便保存对象的状态或者避免修改原对象。对于对象的复制,主要有两种方式:浅拷贝和深拷贝。
浅拷贝
浅拷贝是指只复制对象的一层属性,如果对象的属性值是对象的话,只复制该属性的引用。我们可以使用Object.assign()或者展开运算符...来实现浅拷贝。
let obj1 = { name: "Alice", age: 30 };
let obj2 = Object.assign({}, obj1);
console.log(obj1 === obj2); // false
在上面的代码中,我们使用Object.assign()创建了一个新的对象obj2,复制了obj1的属性。最后我们比较了obj1和obj2是否相等,结果为false。这是因为obj1和obj2是两个不同的对象。
深拷贝
深拷贝是指完全复制一个对象,包括对象的所有层级属性。深拷贝一般使用递归来实现,确保对象及其所有子对象都被复制。
function deepCopy(obj: any): any {
    if (obj === null || typeof obj !== 'object') {
        return obj;
    }
    let copy = Array.isArray(obj) ? [] : {};
    for (let key in obj) {
        copy[key] = deepCopy(obj[key]);
    }
    return copy;
}
let obj1 = { name: "Alice", age: 30, address: { city: "Beijing", postcode: "100000" } };
let obj2 = deepCopy(obj1);
console.log(obj1 === obj2); // false
console.log(obj1.address === obj2.address); // false
在上面的代码中,我们定义了一个深拷贝函数deepCopy(),可以递归地复制一个对象及其所有子对象。通过调用deepCopy()函数,我们实现了对象obj1到对象obj2的深拷贝。最后我们比较了obj1和obj2以及它们的address属性是否相等,结果为false。
对象相等性判断
在JavaScript和TypeScript中,对象的相等性判断主要有两种方式:浅相等性(shallow equality)和深相等性(deep equality)。
浅相等性
浅相等性是指比较两个对象的引用是否相等,即它们是否指向同一块内存地址。我们可以使用===或Object.is()来比较两个对象的引用。
let obj1 = { name: "Alice", age: 30 };
let obj2 = { name: "Alice", age: 30 };
console.log(obj1 === obj2); // false
console.log(Object.is(obj1, obj2)); // false
在上面的代码中,虽然obj1和obj2的属性值相同,但它们是两个不同的对象,因此obj1 === obj2和Object.is(obj1, obj2)的结果均为false。
深相等性
深相等性是指比较两个对象的属性值是否相等,即对象的内容是否相同。由于对象的属性值可能包含其他对象,因此在深相等性判断时需要递归比较对象的所有子属性。
function deepEqual(obj1: any, obj2: any): boolean {
    if (obj1 === obj2) return true;
    if (typeof obj1 !== 'object' || typeof obj2 !== 'object' || obj1 === null || obj2 === null) {
        return false;
    }
    let keys1 = Object.keys(obj1);
    let keys2 = Object.keys(obj2);
    if (keys1.length !== keys2.length) return false;
    for (let key of keys1) {
        if (!keys2.includes(key) || !deepEqual(obj1[key], obj2[key])) {
            return false;
        }
    }
    return true;
}
let obj1 = { name: "Alice", age: 30, address: { city: "Beijing", postcode: "100000" } };
let obj2 = { name: "Alice", age: 30, address: { city: "Beijing", postcode: "100000" } };
let obj3 = { name: "Bob", age: 25, address: { city: "Shanghai", postcode: "200000" } };
console.log(deepEqual(obj1, obj2)); // true
console.log(deepEqual(obj1, obj3)); // false
在上面的代码中,我们定义了一个深相等性判断函数deepEqual(),通过递归比较两个对象的属性值来判断它们是否相等。通过调用deepEqual()函数,我们比较了对象obj1和obj2以及obj1和obj3的相等性,结果分别为true和false。
总结
在TypeScript中,对象赋值会使新变量引用同一块内存地址的对象。当我们比较两个对象时,需要注意对象的引用关系。浅拷贝和深拷贝可以帮助我们复制对象的内容。在比较对象的相等性时,可以使用浅相等性判断或者深相等性判断,根据实际需求选择合适的方式来判断对象是否相等。
极客教程