JavaScript扩展语法与jQuery $.extend对比:传引用与传值差异
为什么两种赋值方式会有引用差异?
这问题戳中了JS对象引用和拷贝的核心点,咱们掰开揉碎了说:
先搞懂前提:c = target到底做了什么?
当你写c = target时,并没有复制整个target对象,只是把c变成了target的一个「引用」——就像给同一个文件加了个新快捷方式,俩变量指向内存里的同一个对象。这时候不管你用c还是target操作对象,修改的都是同一个东西。
为什么c = $.extend(c, update)还是同一引用?
jQuery的$.extend()方法,当你只传两个对象参数时($.extend(目标对象, 源对象)),它的逻辑是直接在目标对象上做修改:把update里的属性一个个合并到c指向的那个原对象里,完全没有创建新对象。
所以执行完这句后,c依然指向原来的那个对象(和target是同一个),自然c === target会返回true。甚至你会发现,target的内容也跟着变了——因为你本质上修改的就是它本身。
要是想让$.extend返回新对象,得这么写:c = $.extend(true, {}, c, update)——第一个参数true表示深拷贝,空对象{}作为新的目标容器,这样才会生成和原对象无关的新对象。
为什么c = {...c, ...update}会创建新变量?
ES6的对象扩展语法{...c}本身就是浅拷贝的一种方式:它会遍历c的所有可枚举属性,把它们复制到一个全新的空对象里,然后再用update的属性覆盖重复的部分。
当你把这个新对象赋值给c时,c就不再指向原来的target了,而是指向了内存里的这个新对象。这时候c和target指向的是两个不同的对象,所以c === target会返回false。
举个直观的代码例子
const target = { name: "Old", nested: { val: 1 } }; let c = target; // 情况1: $.extend原地修改 $.extend(c, { name: "New", nested: { val: 2 } }); console.log(c === target); // true,还是同一个对象 console.log(target.name); // "New",原对象被修改了 // 情况2: 扩展运算符生成新对象 c = {...c, name: "BrandNew", nested: { val: 3 } }; console.log(c === target); // false,c现在是新对象 console.log(target.name); // "New",原对象不受影响
内容的提问来源于stack exchange,提问作者jladbury
相关产品推荐
相关产品推荐

