[Кристианмитк, по-видимому, добавил какое-то объяснение в то время, когда я писал это, но я также оставлю этот ответ здесь, на случай, если альтернативное объяснение кому-нибудь пригодится ...]
То, что Кристианмитк говорит, правильно, но, возможно, могло бы использовать какое-то объяснение.
Причина, по которой ваш код возвращает каждый элемент, заключается в том, что в каждом случае вы проверяете
if (/*...*/ && obj.prop === source.prop) {
//...
}
Но obj.prop
означает «свойство с именем prop
»; то есть вы бы использовали его, чтобы найти значение "xyzzy" объекта, объявленного как
{ prop: "xyzzy" }
Вам нужно проверить свойство, названное значением переменной prop . Это делается с помощью оператора []
.
var prop = "foo";
var obj = { prop: "nope" , foo: "found it" };
// these are true:
obj.prop === "nope"
obj[prop] === "found it"
В вашем тестовом примере, поскольку ни один из рассматриваемых объектов не обладает свойством prop
, все значения равны undefined
. А поскольку JavaScript динамический, можно ссылаться на эти неопределенные значения (без ошибок). И поскольку JavaScript был написан язычниками, undefined === undefined
- это true
.
Существуют и другие способы улучшения кода (для удобства чтения), но я думаю, что это единственный способ помешать его правильной работе. Следующее, на что я посмотрю, это даже после того, как вы сказали
var keys = Object.keys(source);
вы позже несколько раз делаете дополнительные звонки на Object.keys(source)
, когда вы можете просто сказать keys
. Это не так, как утверждают некоторые, вопрос о том, что является «эффективным». Когда-то использование переменной было определенно более эффективным, и, возможно, все-таки это так, но забота об оптимизации на этом уровне не является хорошей идеей. Забота о читабельности - хорошая идея, и как только вы дадите массиву keys
красивое, простое имя (keys
), вы должны его использовать.