Things that You Don't Know About the JavaScript’s Object Constructor
Tags: oop, javascript, tutorial
Published: 2020-01-05 22:41:44

**Subscribe to my email list now at http://jauyeung.net/subscribe/**

**Follow me on Twitter at https://twitter.com/AuMayeung**

In JavaScript, the `Object` constructor lets us create object wrapper with the given values. It will create an empty object if `null` or `undefined` is passed into the Object constructor. If the value passed into the constructor is an object already then, it will return the object.

The `Object` constructor has 2 properties. It has a `length` property that is always 1, and like all other objects, the `Object` constructor has a prototype to get all the property additions to the type Object.

The `Object` constructor has many useful methods that can be used without constructor a new object. Part 1 of this list is below:

`Object.assign()`
-----------------

The `Object.assign()` method makes a shallow copy of an object. The first parameter is a target object that you copy the object to, and the second parameter accepts an object that you want to copy. Note that if the source and target objects have the same properties, the source object’s property value to overwrite the one in the target object. For example, we can write:

```javascript
const target = { a: 1, b: 2 };  
const source = { b: 3, c: 4};
const newObj = Object.assign(target, source);  
console.log(newObj)
```

If we run the code, we will get `{ a: 1, b: 3, c: 4}` . We can also copy arrays. For example, we can write:

```javascript
const targetArr = [1,2];  
const sourceArr = [2,3];
const newArr = Object.assign(targetArr, sourceArr);  
console.log(newArr)
```

We get `[2,3]` logged when we run the code above. For arrays, it will overwrite the whole target array with the source array.

`Object.create()`
-----------------

The `Object.create()` method creates a new object with the object you pass in as the prototype of the new object. For example, we can write:

```javascript
const obj = { a: 1, b: 2, c: 3 };  
const newObj = Object.create(obj);  
console.log(newObj);
```

In the code above, when we log `newObj`, it doesn’t have its own properties that weren’t inherited from `obj`. This is because we only passed in the first argument to the constructor, which is the prototype for the object that’s returned. If we want to add properties that are available only in the returned object, we pass in an object with the property names as keys and the properties `writable`, `configurable`, `enumerable` and `value` as properties of the property name keys, which is called the property descriptor. For example, we can write:

```javascript
const obj = {  
  a: 1,  
  b: 2,  
  c: 3  
};

const childObj = {  
  a: {  
    writable: true,  
    configurable: true,  
    value: 'hello'  
  },  
  d: {  
    writable: true,  
    configurable: true,  
    value: 'hello'  
  }  
}  
const newObj = Object.create(obj, childObj);  
console.log(newObj);
```

In the code above, `writable` means that the property’s value can be changed. `configurable` means the property descriptor may be changed and if the property can be deleted from the object. The `enumerable` property means that the property shows up during enumeration of the properties with the `for...in` loop, and `value` is the value of the property.

If we want to create an object that has properties that can’t be changed, then we set `writable` to `false`, like in the following code:

```javascript
const obj = {  
  a: 1,  
  b: 2,  
  c: 3  
};

const childObj = {  
  a: {  
    writable: false,  
    configurable: true,  
    value: 'hello'  
  },  
  d: {  
    writable: true,  
    configurable: true,  
    value: 'hello'  
  }  
}  
const newObj = Object.create(obj, childObj);  
newObj.a = 1;  
newObj.d = 1;  
console.log(newObj);
```

Notice that the assignment operator has no effect. If we have strict mode enabled, then a `TyepError` will be thrown. We have `{a: “hello”, d: 1}` logged in the `console.log` . This means that `writable` set to `false` is working for the property `a` and `writable` value set to `true` is working for the property `d` .

If we pass in `null` to the constructor, we get an empty object:

```javascript
const nullObj = Object.create(null)  
console.log(nullObj)
```

We will get an error ‘Object prototype may only be an Object or null: undefined’ is we pass in `undefined` as the prototype of an object like in the code below:

```javascript
const undefinedObj = Object.create(undefined);  
console.log(undefinedObj)
```


`Object.defineProperty()`
-------------------------

The `Object.defineProperty()` method defines a new property on an object. The first parameter is the object that you want to add the property to. The second parameter is the name of the property you want to add passed in as a string, and the last parameter is the property descriptor included in the `Object.create()` method when we try to add properties to the returned object. The property descriptor should have the properties `writable` , `configurable` , `enumerable` and `value` as properties of the property name keys. The `writable` means that the property’s value can be changed. `configurable` means the property descriptor may be changed and if the property can be deleted from the object. The `enumerable` property means that the property shows up during enumeration of the properties with the `for...in` loop, and `value` is the value of the property. For example, we can write:

```javascript
let obj = {};
Object.defineProperty(obj, 'a', {  
  writable: false,  
  configurable: true,  
  value: 'hello'  
})console.log(obj.a)  
obj.a  = 1;  
console.log(obj.a)
```

As we can see, the property descriptor acts the same way as in `Object.create()`. When `writable` is `false`, assignment to the property has no effect. If we have strict mode enabled, then a `TyepError` will be thrown.

We can also define getters and setter function for properties called `get` and `set` respectively for a property:

```javascript
let obj = {};  
let value;Object.defineProperty(obj, 'a', {  
  get() {  
    return value;  
  },  
  set(a) {  
    value = a;  
  }  
});console.log(obj.a)  
obj.a = 1;  
console.log(obj.a)
```

As we can see, in the code above, we defined the property `a` for the object `obj` with the `get` and `set` functions to get the value of the property and set the value respectively.

Accessor properties are set on the prototype if we defined it on the prototype, but value properties are set on the current object. If an object inherits non-writable properties, it will still be non-writable on the current object. For example, if we have:

```javascript
let ObjClass = function() {};  
ObjClass.prototype.a = 1;
Object.defineProperty(ObjClass.prototype, "b", {  
  writable: false,  
  value: 1  
});
const obj = new ObjClass();  
ObjClass.prototype.a = 3  
obj.a = 2  
ObjClass.prototype.b = 3  
obj.b = 2  
console.log(obj);
```

Then assigning to property `b` is no effect. If we have strict mode enabled, then a `TyepError` will be thrown.

`Object.defineProperties()`
---------------------------

The `Object.defineProperties` method let us define more than one property on an object. The first parameter of the method is the object that you want to define the properties on, and the second object contains the property names as key and the corresponding property descriptors as values. The property descriptor should have the properties `writable`, `configurable`, `enumerable` and `value` as properties of the property name keys. The `writable` means that the property’s value can be changed. `configurable` means the property descriptor may be changed and if the property can be deleted from the object. The `enumerable` property means that the property shows up during enumeration of the properties with the `for...in` loop, and `value` is the value of the property. For example, we can write:

```javascript
let obj = {}  
Object.defineProperties(obj, {  
  a: {  
    writable: true,  
    configurable: true,  
    value: 'hello'  
  },  
  d: {  
    writable: false,  
    configurable: true,  
    value: 'hello'  
  }  
})  
obj.a = 1;  
obj.d = 1;  
console.log(obj);
```

To add the `a` and `d` properties where `a` ‘s value can change and `d` ‘s value can’t. The `console.log` will show `{a: 1, d: “hello”}` since the value assignment to `d` fails because the `writable` property of property `d` ‘s descriptor is set to `false` . We can also set `configurable` to `false` to prevent it from being deleted or having its property descriptor changed. For example, we can write:

```javascript
let obj = {}  
Object.defineProperties(obj, {  
  a: {  
    writable: true,  
    configurable: true,  
    value: 'hello'  
  },  
  d: {  
    writable: false,  
    configurable: false,  
    value: 'hello'  
  }  
})  
obj.a = 1;  
delete obj.d;  
console.log(obj);
```

If we run the code above, then we can see that the `delete` operator had no effect on property `d` of `obj`.

`Object.entries()`
------------------

The `Object.entries()` method returns an array of key-value pairs of an object that are enumerable by the `for...in` loop. They are returned in the same order as they are in if they are iterated with the `for...in` loop. Each entry of the array will have the key as the first element and the value of the corresponding key as the second element. For example, we can use it to loop through the properties of an object in the following code:

```javascript
const obj = {  
  a: 1,  
  b: 2  
};
for (let [key, value] of Object.entries(obj)) {  
  console.log(key, value);  
}
```

When we run the code above, we get `a 1` and `b 2`. These are the key-value pairs of this object.

`Object.freeze()`
-----------------

The `Object.freeze()` method freezes an object. This means that all properties’ values in an object can’t be changed. Also, new properties can’t be added to it, and existing property descriptors for the frozen object can’t be changed. The object is frozen in place. This method doesn’t return a new frozen object. Instead, it returns the original object before it’s frozen. The frozen object’s prototype also can’t be changed. For example, if we run the following to freeze an object:

```javascript
const obj = {  
  a: 1  
};
Object.freeze(obj);
obj.a = 2;
console.log(obj.a);
```

We get that `obj.a` is still 1. This is because the object’s properties’ values can’t be changed. If we have strict mode enabled, a `TypeError` will be raised. It’s important to note that values that are objects can still be modified. For example, if we have the following code:

```javascript
const obj = {  
  a: 1,  
  b: {  
    c: 2  
  }  
};
Object.freeze(obj);
obj.b.c = 3;
console.log(obj.b.c);
```

Then `obj.b.c` is 3 since `Object.freeze` doesn’t freeze properties that are inside of nested objects unless they’re frozen explicitly. So if we have:

```javascript
const obj = {  
  a: 1,  
  b: {  
    c: 2  
  }  
};
Object.freeze(obj);  
Object.freeze(obj.b);
obj.b.c = 3;
console.log(obj.b.c);
```

Then `obj.b.c` is 2 since we frozen `obj.b` so that we can’t modify the value of `obj.b` .

The `Object` constructor has many more methods for constructing objects from an array of arrays with key and value of properties, and also methods to get property descriptors from objects, property names, property symbols, gets the keys of objects and prevent properties from being added or deleted or modify their property descriptors.