Prototype Methods, Objects

Prototype Methods, Objects

Prototype Methods, Objects Without __proto__


Let’s first explore the modern methods for setting up a prototype.

Amongst them are:

  1. Object.create(proto[, descriptors]). This method is used for creating an empty object with given proto as [[Prototype]], as well as, optional property descriptors.
  2. Object.getPrototypeOf(obj). This one helps to return the [Prototype]] of the obj.
  3. Object.setPrototypeOf(obj, proto). The method is aimed at setting the [[Prototype]] of the obj to proto.

So, you can use the mentioned methods instead of the __proto__.

Take a look at the following example:

let animal = {

  speaks: true

};

let dog = Object.create(animal);// create a new object with animal as a prototype

console.log(dog.speaks); // true

console.log(Object.getPrototypeOf(dog) === animal); // true

Object.setPrototypeOf(dog, {}); // change the prototype of  dog to {}

There is an alternative argument for Object.create: property descriptors. You have the option of providing additional properties to the object there.

For example:

let animal = {

  speaks: true

};

let dog = Object.create(animal, {

  runs: {

    value: true

  }

});

console.log(dog.runs); // true

For performing an object cloning, it’s more convenient to use Object.create than copying properties in for..in.

The example looks like this:

// fully identical shallow clone of obj
let clone = Object.create(Object.getPrototypeOf(obj), Object.getOwnPropertyDescriptors(obj));

The call mentioned above creates the exact copy of obj, which includes all the properties: non-enumerable and enumerable, data properties, setters/getters, and with the suitable [[Prototype]].

Short History

There are many ways of managing the [[Prototype]].

One of the reasons is that the “prototype” property has worked since ancient times. In 2012, Object.create was added to the standard. It started to allow creating objects with __proto__ accessor.

Later, in 2015, Object.setPrototypeOf and Object.getPrototypeOf appeared in the standard for performing the same functionality as __proto__.

Nowadays, all these methods are at the developers’ disposal.

Technically, it is possible to get/set [[Prototype]] at any time. But, commonly, it is set once while creating the object and is not modified anymore. Changing a prototype with Object.setPrototypeOf or obj.__proto__= can be considered a slow operation. The reason is that it breaks internal optimizations for object property access operations.

"Very Plain" Objects

You can use objects as associative arrays for storing key/value pairs. But in the event of trying to store user-provided keys inside it, a unique error may occur: all the keys will work well except "__proto__".

Look at this example:

let obj = {};

let key = prompt("What is the key value?", "__proto__");

obj[key] = "some value";

console.log(obj[key]); // [object Object], not "some value"!

Here when the user types __proto__, the assignment is ignored. Thus, the __proto__ property is unique. It can be either null or an object. A string can’t transform into a prototype.

So, the main problem is that "__proto__" is not saved accurately. It’s a bug. Some unexpected things can happen while assigning toString that is a function by default.

To avoid such kinds of problems, first, you can switch to using Map .

The Object may also be helpful. The __proto__ is not an object property, but an accessor property of Object.prototype.

Check out this case:

Prototypemethods1

In obj.__proto__ is set or read, the appropriate setter/getter is called from its prototype, as well as, sets/gets [[Prototype]].

If you intend to use an object as an associative array, you can implement it with a trick.

Here is how to do it:

let obj = Object.create(null);

let key = prompt("What's the key value?", "__proto__");

obj[key] = "some value";

console.log(obj[key]); // "some value"

Object.create(null) generates an empty object without a prototype:

Prototypemethods2

It can be assumed that there isn’t any inherited getter/setter for __proto__. It is handled as an ordinary data property.

Such objects can be named “very plain” because they are more straightforward than the ordinary plain object {...}.

The disadvantage is that such objects lack built-in object methods (toString).

For instance:

let obj = Object.create(null);

console.log(obj); // Error (no toString)

Usually, it’s fine for associative arrays.

Soeng Souy

Soeng Souy

Website that learns and reads, PHP, Framework Laravel, How to and download Admin template sample source code free.

Post a Comment

CAN FEEDBACK
close