Create an empty object in JavaScript with {} or new Object()?
Objects
There is no benefit to using new Object()
, whereas {}
can make your code more compact, and more readable.
For defining empty objects they're technically the same. The {}
syntax is shorter, neater (less Java-ish), and allows you to instantly populate the object inline - like so:
var myObject = {
title: 'Frog',
url: '/img/picture.jpg',
width: 300,
height: 200
};
Arrays
For arrays, there's similarly almost no benefit to ever using new Array()
over []
— with one minor exception:
var emptyArray = new Array(100);
creates a 100 item long array with all slots containing undefined
, which may be nice/useful in certain situations (such as (new Array(9)).join('Na-Na ') + 'Batman!'
).
My recommendation
- Never use
new Object();
— it's clunkier than{}
and looks silly. - Always use
[]
— except when you need to quickly create an "empty" array with a predefined length.
Creating a new empty object in JavaScript
The object referred to by Bar
is shared between each Foo
instance.
I don't really see the point of putting the logic into two objects, you can do this with just one constructor function:
function Foo() {
this.__words = {};
}
Foo.prototype.addWord = function(word, amount) {
this.__words[word] = amount;
}
var foo = new Foo();
foo.addWord("hello",7);
var bar = new Foo();
bar.addWord("world",9);
If you really have to separate the functionality, then make Bar
a constructor function as well and create a new instance inside the Foo
constructor method:
function Foo() {
this.bar = new Bar();
}
function Bar() {
this.__words = {};
}
Bar.prototype.addWord = function(word, amount) {
this.__words[word] = amount;
}
Create an empty object/array, based on an existing object/array
You can use constructor
property of thing
. And don't use new
as variable name.
const transf = (thing) => {
const newelm = new thing.constructor()
}
Demo:
const transf = (thing) => { return new thing.constructor()}
console.log(transf(['arra']))console.log(transf({key:'value'}))
Why Object.assign({}, ...) with an empty object literal when other objects are also passed in?
When you use Object.assign
, the first object you give it will have all the rest of the objects merged into it. That is to say, the first object will be mutated.
If you want to avoid mutating the objects you're merging, it's helpful to pass in the empty object as the first parameter to prevent any of the component objects from changing.
Here's an example demonstrating the difference:
const obj1 = { foo: "bar"}
const obj2 = { key: "value"}
// Here, obj1 is the same after the Object.assign callconsole.log(Object.assign({}, obj1, obj2));console.log(obj1)console.log(obj2)
console.log("\n\n")
// Note that after this call, obj1 holds both keys. So this will mutate it:console.log(Object.assign(obj1, obj2));console.log(obj1) // This is different nowconsole.log(obj2)
How to create an empty object which has defined value type
You can use an empty object literal and a type assertion to tell the compiler what the expected type of the property will be:
let rockHardObs = {
'Lady': { } as { [key: string]: Gaga }
}
TypeScript empty object for a typed variable
Caveats
Here are two worthy caveats from the comments.
Either you want user to be of type
User | {}
orPartial<User>
, or you need to redefine theUser
type to allow an empty object. Right now, the compiler is correctly telling you that user is not a User. –jcalz
I don't think this should be considered a proper answer because it creates an inconsistent instance of the type, undermining the whole purpose of TypeScript. In this example, the property
Username
is left undefined, while the type annotation is saying it can't be undefined. –Ian Liu Rodrigues
Answer
One of the design goals of TypeScript is to "strike a balance between correctness and productivity." If it will be productive for you to do this, use Type Assertions to create empty objects for typed variables.
type User = {
Username: string;
Email: string;
}
const user01 = {} as User;
const user02 = <User>{};
user01.Email = "foo@bar.com";
Here is a working example for you.
Create an empty object at deep path with lodash
There's a _.deepDefault
method in an extra lodash-deep library that checks if the value at the propertyPath
resolves to undefined
, and sets it to defaultValue
if this is the case:
var descendant = _.deepDefault(object, 'some.deep.path', {});
That library is not updated anymore because Lodash now supports most of the functionality natively so here's an implementation as a lodash mixin function:
function getOrSetDefault(object, path, defaultValue) {
const descendant = _.get(object, path);
if (descendant === undefined) {
_.set(object, path, defaultValue);
}
return descendant;
}
_.mixin({ getOrSetDefault });
const a = _.getOrSetDefault(object, 'some.deep.path', 42);
const b = _.getOrSetDefault(object, 'some.other.deep.path', {});
b.c = 42;
With the new optional chaining operator and a logical nullish assignment there would be no need to use lodash for this particular case (if it is acceptable to populate/define some.deep.path
with a default value), e.g.:
some?.deep?.path ??= {}
const { foo } = some.deep.path
Unfortunately optional chaining assignments are not available yet.
See https://stackoverflow.com/a/58882121/1949503
There would be just one drawback in that there'll be a need to repeat property accessors (some.deep.path
) to retrieve the value. However in this case we will have autocompletion using Typescript/JSDoc unlike in lodash funcions' path argument (either string or array)
If there's only a need to get value at path the vanilla try/catch
could be sufficient:
let foo: Foo;
try {
foo = some.deep.path.foo
} catch {}
Related Topics
Find Day Difference Between Two Dates (Excluding Weekend Days)
How to Send a Message to a Particular Client with Socket.Io
Why Are Certain Function Calls Termed "Illegal Invocations" in JavaScript
How to Use Redis Publish/Subscribe with Nodejs to Notify Clients When Data Values Change
How to Round Float Numbers in JavaScript
How JavaScript Closures Are Garbage Collected
Chart.Js - Drawing an Arbitrary Vertical Line
What Is Node_Env and How to Use It in Express
Javascript: Call a Function After Specific Time Period
Pagination on a List Using Ng-Repeat
Convert String Array Representation Back to an Array
How to Access Accelerometer/Gyroscope Data from JavaScript
How to Set a Cookie with Expire Time
How to Skip Over an Element in .Map()
Call a Vue.Js Component Method from Outside the Component
Run JavaScript in Visual Studio Code
JavaScript Ie Detection, Why Not Use Simple Conditional Comments