对象内部的函数不希望通过引用进行更改

时间:2018-04-25 09:48:22

标签: javascript

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。

因为对象以某种方式将信息保存在可以找到它的道具上。

非常感谢。

5 个答案:

答案 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"如果你在感情时真的克隆了数据,那么ObjectArray可能需要大量的内存泄漏(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