Hay我有这段代码:
let callback2 = () => console.warn('Old one');
let props2 = {
callback2
}
function test(props) {
props.callback2 = () => console.warn('siema');
}
test(props2);
callback2();
这里也是小提琴: https://jsfiddle.net/4g3p9ego/
该代码的结果是“旧的”而不是“siema”。 但功能也不是原始和对象,所以我期待结果'siema'。
你知道我为什么得到“老一号”的消息吗?
==========编辑:扩展示例===========
let callback2 = () => console.warn('Old one');
let moreTest = {
moreTest: 'moreTest'
}
let props2 = {
callback2,
moreTestObject: moreTest
}
function test(props) {
props.callback2 = () => console.warn('siema');
props.moreTestObject.moreTest = 'Changed';
}
test(props2);
console.warn(moreTest)
callback2();
为什么在这里我可以改变对象?但是不能改变功能吗?
我得到了:
{moreTest:“已更改”}
“老一”
预期:
{moreTest:“已更改”}
“siema”
==========解决方案===========
我理解所有,我的困惑是因为我不知道对象{}总是知道如何找到它的道具。所以即使我有
testObj = {
inside: 'inside' // 0x123
}
当我调用test.Obj对象知道它需要转到0x123。并改变testObj,如:
testObj.inside = 'outside' //0x125
使用它,testObj.inside和object知道转到0x125。
因为对象以某种方式将信息保存在可以找到它的道具上。
非常感谢。
答案 0 :(得分:2)
但功能不是原始
这没关系。你永远不会尝试修改一个功能。
对象也不是原语。
首先,您创建一个对象并将原始callback2
函数分配给callback2
属性。
let props2 = { callback2 }
然后将props2
(对该对象的引用)的值复制到函数参数。
test(props2);
然后用新值(一个调用callback2
的函数)覆盖该对象的console.warn
属性的值。
props.callback2 = () => console.warn('siema');
然后你打电话:
callback2();
...但是仍然的变量值是对原始函数的引用。你永远不会改变它。
为什么在这里我可以改变对象?但是不能改变功能吗?
x = y
更改左边的内容。
下面:
props.moreTestObject.moreTest = 'Changed';
左边的东西是moreTest
引用的对象的props.moreTestObject
属性。
下面:
props.callback2 = () => console.warn('siema');
左边的东西是callback2
引用的对象的props
属性。
左边的东西不是功能。
在为其赋值之前它保持的值是对函数的引用,但这并不重要,因为您用新的值覆盖了该值。
callback2
变量的值也是对该函数的引用(由props.callback2
的旧值引用)但这并不重要,因为您不是更改callback2
变量的值。
答案 1 :(得分:1)
在函数内部执行的操作不会保留在函数外部。你需要返回道具
function test(props) {
props.callback2 = () => console.warn('siema');
return props
}
props2 = test(props2);
答案 2 :(得分:1)
是因为您不能替换callback2
变量但props
对象的属性。
// you create variable with 1 reference : exemple is our memory addr 0x123
let callback2 = () => console.warn('Old one');
// You copy this reference to another variable : props2 = 0x123 where 0x123 is reference from previous line.
let props2 = {
callback2
}
function test(props) {
let {callback2} = props;
// You replace old reference by new one, this not impact callback2 variable, just remove 1 reference to callback2 and create new one.
props.callback2 = () => console.warn('siema'); // Replace 0x123 reference by new one, exemple 0x456
}
test(props2);
callback2();
JavaScript中的count reference
全部都是garbage collector
。 Official documentation
" Complexe type"如果你在感情时真的克隆了数据,那么Object
和Array
可能需要大量的内存泄漏(myVar2 = myVar1)。
为了防止这种情况,Javascript会复制您的数据引用(内存中的地址)而不是复制完整数据。
您的案件可能会让您感到困惑。
行:props.callback2 = () => console.warn('siema');
不会影响共享相同内存引用的其他变量。您可以使用新的匿名方法() => console.warn('siema');
---更新1 ---
let callback2 = () => console.warn('Old one');
// This create Ox123 reference in memory.
let moreTest = {
moreTest: 'moreTest'
}
let props2 = {
callback2,
moreTestObject: moreTest // where ou copy Ox123 reference to moreTestObject property
}
function test(props) {
props.callback2 = () => console.warn('siema');
// where you edit Ox123 memory reference, is why you impact both variable who have same reference.
// props.moreTestObject.moreTest = 'Changed';
// here you replace Ox123 memory reference by new one : 0x456. This will not impact moreTest original reference because you don't update Ox123 but replace by new entire reference in moreTestObject property
props.moreTestObject = { moreTest: 'Changed'};
}
test(props2);
console.warn(moreTest)
callback2();
编辑2
根据你的上一次更新,除了做这样的事情之外我别无选择。或者更优雅的第二个样本
//Change this to var as global variable.
var callback2 = () => console.warn('Old one');
let moreTest = {
moreTest: 'moreTest'
}
let props2 = {
callback2,
moreTestObject: moreTest
}
function test(props) {
// I see no choice than override both here.
callback2 = props.callback2 = () => console.warn('siema');
}
test(props2);
console.warn(moreTest)
callback2();
更优雅:
let util = {
foo : () => console.warn('Old one')
};
let second = {
util
}
let third = {
util
}
function test(props) {
props.foo = () => console.warn('siema');
}
test(util);
util.foo(); // Output `siema`
second.util.foo(); // Output `siema`
third.util.foo(); // Output `siema`
答案 3 :(得分:0)
你知道我为什么得到“老一号”的消息吗?
let {callback2} = props;
内test()
的可访问性仅限于初始化的块,即test
函数。
在外部测试中,它将保留
的旧绑定let callback2 = () => console.warn('Old one');
从let
移除let {callback2} = props;
以设置位于外部的新引用。
function test(props) {
callback2 = props.callback2;
// callback2 = () => console.warn('siema');
props.callback2 = () => console.warn('siema');
}
答案 4 :(得分:-1)
如果您致电props2.callback2()
,则会输出siema
。