In Lodash, both _.assign
and _.assignIn
are ways to copy source objects’ properties into target object. According the documentation, _.assign
processes own enumerable string keyed properties, while _.assignIn
processes both own and inherited source properties. There’re also other companion functions like _.forOwn
and _.forIn
, _.has
and _.hasIn
. So what’s the difference between them?
In brief, the In
in latter methods implies the way for...in
loop behaves, which iterates all enumerable properties of the object itself and those the object inherits from its constructor’s prototype. JavaScript has an inheritance mechanism called prototype chain. When iterating an object’s properties with for...in
or _.forIn
, all properties appeared in the object and its prototype are processed, until the prototype resolves to null
. Here’s the example code taken from Lodash’s doc:
1 | function Foo() { this.a = 1; } |
How _.assign
Picks Properties
Let’s dissect the phrase “own enumerable string-keys properties” into three parts.
Own Property
JavaScript is a prototype-based language, but there’re several ways to simulate class and instance, like object literal, function prototype, Object.create
, and the newly added class
keyword. In either case, we can use Object.prototype.hasOwnProperty()
to determine if the property is inherited or not.
1 | let foo = new Foo(); |
Object.getOwnPropertyNames()
and Object.keys()
can retrieve all properties defined directly in the object, except that Object.keys()
only returns enumerable keys (see next section).
1 | let o1 = {a: 1}; |
Enumerable Property
Object property can be defined with either data descriptor or accessor descriptor. Among data descriptor options, the enumerable
boolean indicates whether this property shows in for...in
or Object.keys()
.
1 | let o = {}; |
You can refer to Object.defineProperty() for more information.
String-keyed Property
Before ES6, object’s keys are always String. ES6 introduces a new primitive type Symbol, which can be used as a key for private property. Symbol property is non-enumerable.
1 | let s = Symbol(); |
There’s a nice Detection Table to help you figure out which built-in methods process enumerable or inherited properties.
_.assign
and _.assignIn
Implementation
Both methods calls _.keys
and _.keysIn
respectively. _.keys
calls Object.keys()
and _.keysIn
uses for...in
loop. Actually Object.keys()
is not difficult to implement. As mentioned above, for...in
can be used to retrieve both own and inherited properties, while hasOwnProperty
determines whether this property is defined in the object itself.
1 | function keys(object) { |
Object.assign()
does the same thing as _.assign()
. Use Lodash if you need to run your code on older browsers.