函数实参为对象时的陷阱
上周在实现某个弹层功能的时候,用到了rc-util
里的 contains
方法函数, 结果 code-review
的时候同事对该代码提出了疑问:
export default function contains(root, n) {
let node = n;
while (node) {
if (node === root) {
return true;
}
node = node.parentNode;
}
return false;
}
上述代码是 antd
内部抽象的一个工具方法,用来判断某个dom是否为另一个dom的祖先节点。
同事疑问的是 let node = n;
这段代码是不是多余的?
首先一开始的理解是 函数参数 n
是一个对象,一个dom
节点对象。
如果用 node
保存 n
的值,防止 node = node.parentNode
这段代码执行的时候,会改变传入的实参 n
对应的值。
毕竟以下的代码我们都很熟悉:
function contains(root, n) {
if(n) {
n.a = 3
}
}
const A = {a:1};
const B = {a:2};
contains(A,B)
console.log(B) // {a:3}
即当实参为对象时,函数内部是可以改变该对象的值从而影响函数之外的实参。
但是测试另外一段代码,发现和理解的不一样:
function contains(root, n) {
if(n) {
n = {a:3}
}
}
const A = {a:1};
const B = {a:2}
contains(A,B)
console.log(B) // {a:2}
即 n.a = 3
和 n = {a:3}
这两段代码是不一样的。
网上也有相关资料,其实可以简单的理解为: 当函数一开始执行时,n
是指向实参 B
的一个引用。
n.a = 3
是在引用上再关联了一个属性,此时和 B
还是同一个引用,因此会改变实参B
的值。
而 n = {a:3}
则使得 n
不再指向实参 B
, 而是指向一个新对象{a:3}
,也就是 n
与 B
彻底断绝了关系,因此不会改变实参 B
的值。
是不是可以给蚂蚁的团队提个issue建议删除该代码,不过有这句代码也不会有什么bug 该行代码可能是为了符合 eslint
规范: 不对函数的参数进行赋值。链接
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论