Underscore.js - extendOwn和extend有什么区别?

14

浏览underscorejs的方法列表时,我注意到一个以前没见过的方法:extendOwn

此方法的文档如下:

extendOwn _.extendOwn(destination, *sources) 别名: assign

类似于 extend,但只会复制源对象中的自有属性(own properties)到目标对象中。

我明白如何使用并了解.extend()的功能......但是我却无法理解它与.extendOwn()的区别。

我尝试使用.extend().extendOwn()扩展一些对象,以查看是否存在明显的差异——但它们似乎都产生相同的结果。

var a = {
    foo: false
};

var b = {
    bar: true
};

// This will produce { foo: false, bar: true }; ..just like _.extend() would =\
_.extendOwn( a, b );

对这个谜团的任何洞察都将不胜感激!


我没有 - 不过那是个好主意,谢谢。 - Jonathon Hibbard
嘿,我刚刚读了源代码。有趣的是,它归结为使用_.keys与_.allKeys - 这又不同于一个使用nativeKeys和以下内容的:for (var key in obj) if (_.has(obj, key)) keys.push(key);而另一个则不这样做。不知道为什么extendOwn甚至是必要的,对我来说仍然有点神秘。 - Jonathon Hibbard
2个回答

12

"拥有属性"是JS中的一个技术术语。一个对象的拥有属性是它没有继承的属性。

下面是一个简短的代码片段,展示了extendextendOwn的不同行为:

// lines have length
line = { length: 4 }

// planes have width and inherit length
plane = Object.create(line)
plane.width = 5
plane.length  // 4

// making a cube object, using extend
cube = _.extend({ height: 6 }, plane)
cube.length  // 4

// making a cube object, using extendOwn
notACube = _.extendOwn({ height: 6 }, plane)
notACube.length  // undefined

正如您所看到的,extendOwn 仅复制了直接定义在源对象上的属性,而 extend 还复制了沿其原型链定义的属性。还要注意与 _.has 的对称性:

_.has(plane, 'width')   // true
_.has(plane, 'length')  // false

1
这个答案很有帮助。Underscore文档在解释这个问题方面真的很糟糕。 - luxon

9

对于任何想知道答案的人,一个好的地方是在这里找到:https://github.com/jashkenas/underscore/search?q=extendOwn&type=Issues&utf8=%E2%9C%93

更新

对于有兴趣的人,答案是extendOwnObject.assign是同义词,实现有点不同。Underscorejs只是添加了一种替代方法。他们没有通过新实现覆盖assign并将其称为_.assign,而是称其为_.extendOwn(其中_.assign_.extendOwn的别名)。

这种命名规则的原因可以理解,但是我认为有点令人困惑。你知道,Object.assign是ES6官方命名的方法/逻辑,我们通常称之为“extend”(由像jQuery和Underscore这样的工具调用)。Underscore团队的决定是他们决定将主/父方法称为extendOwn以遵循其自己的内部标准。将主要方法命名为_.assign会(对于Underscore团队来说)与他们的直觉相反,因为它会混淆“extend”的含义。通过将其称为extendOwn,他们意味着该方法与“extend”执行相同的操作,但基于ES6实现的此功能被称为“assign”。
基本上,这里存在一个悖论,他们需要做出决定。要么坚持我们所知的“扩展”约定,要么允许“分配”,这只会与原始名称发生冲突(这也可能开始引起人们质疑为什么他们仍然称另一种方法为“扩展”而不是assignSomethinghere)。
长话短说- extendOwn是ES6的Object.assign的Underscore版本。他们只是将其命名为extendOwn以保持与相同的命名约定,即命名为extend。

4
我猜现在阅读 MDN 上的 hasOwnProperty 文章可能会很有帮助。 - mu is too short
你在评论中提到的 in 循环内的 _.has 调用可能只是 obj.hasOwnProperty(key) 的别名。extendOwn 属性不会遍历原型,但 extend 会;如果你只是使用简单对象(即 o = { ... }),则不会有任何区别。 - mu is too short
2
这并没有回答问题。您提供了关于为什么事物被命名为它们所用名称的历史描述,但并没有解释两种方法之间的功能差异。 - Max Barraclough
1
请重新阅读已接受答案中链接的文章(以及@muistooshort在上面的评论),它们很好地解释了功能问题的差异。 - Jonathon Hibbard

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接