2016-02-25 130 views
0

我写了一个JavaScript函数来扩展一个对象,其中包含一个遵循这种表示法的属性:“a.b.c”。该功能完美无缺(迄今为止),但我回顾了我的代码为什么它的工作后,我不明白。我假设有一个JavaScript范围的解释,也许for循环?但我想知道是否有人能够正确地向我解释这一点。为什么扩展功能起作用?

var extend = (target, targetProperty, value) => { 
    var targetProperties = targetProperty.split("."); 

    for (var i = 0, len = targetProperties.length; i < len; i++) { 
    var part = targetProperties[i]; 

    if (i == len - 1) { 
     target[part] = value; 
     break; 
    } 

    if (!target[part]) { 
     target[part] = {}; 
    } 

    target = target[part]; 
    } 
} 

var myObject = {myProperty: "Hello"}; 

console.log(myObject); 

extend(myObject, "a.b.c", "World"); 

console.log(myObject); 

这是非常简单的,据我所知,“目标”通过引用进来的,因为它是一个对象,我不明白是怎么上线target = target[part];中传递的原始对象的一部分不会被该线上新创建的空对象完全覆盖target[part] = {};

谢谢!

+0

我想你的意思是'target = target [part]' – kmiyashiro

回答

0

原因是因为break;,它突破了循环,并且不会在其后面运行代码。

代码break后,剩下的就是处理情况:

  1. 将您要设置一个中间属性是falsey。即。您正在尝试设置路径foo.bar.baz,但未定义foo.bar,因此在设置foo.bar.baz之前,它将分配{}foo.bar
  2. 中间属性为truthy,在这种情况下,它将该中间属性设置为要处理的新目标。

这是错误的代码,因为如果中间属性不是Object?例如,如果你有这样的对象:

{ 
    foo: 1 
} 

你想设置foo.bar

extend(myObject, 'foo.bar', 'wombat') 

它会尝试设置foo.bar'wombat',但foo1。你如何设置1.bar?你不能。

+0

你从来没有试过? '(1).bar ='袋熊';'完美无瑕。 – Bergi

+0

按照你认为的那样工作?或者只是不会抛出一个错误? – kmiyashiro

+0

我的意思是不会抛出错误;当然,原始值不具有属性。但是我不认为代码会因此而变得糟糕 - 这是一个例外,可以预期这种情况。你如何建议改进代码来应对这种情况? – Bergi

0

target只存在于您的函数范围内,因此更改target变量的值只会在函数范围内更改它。

您正在更新引用而不是更改对象。

+0

如果是这样的话,那么为什么在执行函数后,myObject会添加所有正确的属性?以及运行该功能之前的原始属性仍保留。 – Ross

+0

@Ross:该函数会改变对象的属性。它不覆盖你的对象。 – Bergi

+0

@Bergi:我很初级,但我也不认为我正确地问了这个问题。 'target'是该函数中对'myObject'的引用。在函数结束时,我将target指定为一个新的空对象'target = target [part];'。我只是不确定为什么myObject不会成为空虚的对象,而是保持机智。道歉,如果我只是没有得到它:) – Ross