Lodash _.toPlainObject() method
What you’ll learn
- What
_.toPlainObject(value)really does—and the common backwards explanation to ignore. - How it walks the prototype chain via
_.keysInto surface inherited enumerable keys. - The intended pairing with
_.assignfor prototype-aware merging. - What happens to primitives, strings, arrays, and class instances.
Prerequisites
You can tell own properties (from Object.keys) apart from inherited properties (from a class prototype or Object.create).
- You know what a plain object means in lodash terms (prototype =
Object.prototypeornull). - Try-it labs load lodash from the CDN.
Overview
One line of implementation: return _.copyObject(value, _.keysIn(value)); — keysIn includes inherited enumerable keys, so the function flattens the chain rather than strips it.
Inherited → own
Prototype props become own props of the new plain object.
Plain prototype
Result’s prototype is always Object.prototype.
Shallow copy
Nested values are shared references—not deep-cloned.
Syntax
_.toPlainObject(value) - value: the value to convert.
- Returns: a new plain
Objectwhose own properties are the input’s enumerable keys (own and inherited).
The lodash docs example, verified
The official docs show why this function exists: pair it with _.assign when you want inherited keys included in a merge.
import assign from "lodash/assign";
import toPlainObject from "lodash/toPlainObject";
function Foo() {
this.b = 2;
}
Foo.prototype.c = 3;
console.log("plain raw: " + JSON.stringify(toPlainObject(new Foo())));
console.log("assign raw: " + JSON.stringify(assign({ a: 1 }, new Foo()))); // { a:1, b:2 }
console.log("assign wrapped: " + JSON.stringify(assign({ a: 1 }, toPlainObject(new Foo())))); // { a:1, b:2, c:3 } Object.create chains flatten too
When an object inherits from a custom prototype object, _.toPlainObject rolls every enumerable inherited key onto the new plain object.
import toPlainObject from "lodash/toPlainObject";
const proto = { protoProp: "inherited" };
const obj = Object.create(proto);
obj.ownProp = "own";
const flat = toPlainObject(obj);
console.log("flat: " + JSON.stringify(flat));
console.log("hasOwn protoProp: " + Object.prototype.hasOwnProperty.call(flat, "protoProp"));
console.log("Object.prototype: " + (Object.getPrototypeOf(flat) === Object.prototype)); Primitives, strings, arrays
No keysIn → {}. Strings expose indexed character keys but not length (it’s non-enumerable). Arrays behave the same way.
import toPlainObject from "lodash/toPlainObject";
console.log(
"null: " + JSON.stringify(toPlainObject(null)) + "\n" + // {}
"42: " + JSON.stringify(toPlainObject(42)) + "\n" + // {}
"'abc': " + JSON.stringify(toPlainObject("abc")) + "\n" + // {"0":"a","1":"b","2":"c"}
"[1,2,3]: " + JSON.stringify(toPlainObject([1, 2, 3])) // {"0":1,"1":2,"2":3}
); 📋 _.toPlainObject vs related operations
| API / pattern | What gets copied |
|---|---|
_.toPlainObject(x) | All enumerable string-keyed properties (own and inherited) onto a new plain object. |
{ ...x } | Only own enumerable string keys—ignores the prototype chain. |
Object.assign({}, x) | Same as spread: own enumerable keys only. |
_.assign({}, x) | Own enumerable keys only (Object.keys). |
_.assignIn({}, x) | Own and inherited enumerable keys—the close cousin of _.toPlainObject. |
Pitfalls to avoid
It does not strip inherited props
Several blog posts (including older versions of this very page) claim the opposite. The lodash docs are clear: this method flattens inherited keys onto the result.
Shallow only
Nested objects/arrays are copied by reference. Mutating result.nested will mutate input.nested. Use _.cloneDeep when you need an independent copy.
Hidden props are skipped
String’s length, getters defined with { enumerable: false }, and symbol keys are not copied. Only enumerable string-keyed properties make it through.
❓ FAQ
Summary
- Purpose: flatten an object’s prototype-inherited enumerable string keys into own keys of a fresh plain object.
- Remember: inherited → own, not the other way around. Pair with
_.assignfor prototype-aware merging. - Next: head to Lodash _.toSafeInteger() —
_.toSafeIntegeris up next.
_.toPlainObject uses keysIn under the hood—the same walker as _.assignIn—so it picks up inherited enumerable keys. The output object always has Object.prototype as its prototype, even if the input had a custom one.
7 people found this page helpful
