Properly segregating data across various instances of JavaScript objects

Until today, I was completely unaware of this issue and now I am eager to discover the most effective way to navigate around it. The problem arises when two distinct objects are instantiated from the same constructor function - they end up sharing the same prototype. This results in a scenario where altering the prototype of one object affects all other objects as well.

Let's take a look at an example:

function A(obj) {

}

A.prototype = {

    events: {
        one: 1
    }

};


var b = new A();

console.log(b.events);

var c = new A();

console.log(c.events);

b.events.x = 2;

console.log(b.events);
console.log(c.events);  //oops, c also inherited x from b

What a confusing situation! Is there a superior method to work around this?

I proposed a solution below, but I'm curious if there is a more efficient approach:

var _ = require('underscore');

function A(obj) {
    if (obj == null) {
        obj = {};
    }
    if(obj.events == null){
        obj.events = {};
    }
    this.events = _.extend(obj.events, A.prototype.events);
}

A.prototype = {

    events: {
        one: 1
    }

};


var b = new A({events:{three:3}});

console.log(b.events);

var c = new A({events:{four:4}});

console.log(c.events);

b.events.x = 2;

console.log(b.events);
console.log(c.events); //now it's improved...(quite puzzling)

Answer №1

It's important to understand that the prototype in JavaScript is shared among all instances of a particular object for reasons such as storage efficiency. This means that anything placed in the prototype will be identical across all instances.

If you need certain properties to have unique values for each instance, then they should not be included in the prototype. Instead, these properties should be set using the 'this' pointer within the constructor.

For example, if your 'events' property is meant to be different for each instance, initialize it within the constructor like so:

function A(obj) {
    this.events = {one: 1};
}

Make sure to remove it from the prototype to ensure uniqueness for each instance. The prototype is best suited for methods and should generally not be used for mutable data.

Here is a working code example:

function A() {
    this.events = {one: 1};
}

var x = new A();
var y = new A();

log(x.events);
log(y.events);
log("--------------");

x.events.one = 2;
y.events.one = 3;

log(x.events);
log(y.events);

function log(x) {
    var d = document.createElement("div");
    if (typeof x === "object") {
        x = JSON.stringify(x);
    }
    d.textContent = x;
    document.body.appendChild(d);
}

Answer №2

What's with all the complexity?

const myFunction = (object) => {
    let events = {
        one: 1
    };
}

Answer №3

It's important not to store variables in the prototype, but rather use them in the constructor function. A suitable solution for your situation would be:

    function B(obj) {
        this.data = {
            two: 2
        };
    }


    var d = new B();

    console.log(d.data);

    var e = new B();

    console.log(e.data);

    d.data.y = 3;

    console.log(d.data);
    console.log(e.data);

Answer №4

The initial step is grasping the concept of prototypical inheritance.

Prototypical inheritance essentially involves a live reference to a specific value...

Beneath the surface,

A.prototype.method = function bar() {};

var b = new B();
b.__proto__.method === b.constructor.prototype.method;
b.__proto__ === A.prototype;

unless you decide to alter the value of `.prototype' to a new object... ...then your existing instances will connect to the old prototype object, while the new instances will link to the updated prototype object.

This delves into the realms of deep-copy versus shallow-copy, value versus reference essence. There isn't Java/C# inheritance with private variables, unless implemented through closures (which bear no resemblance to Java/C#).

If you're planning to assign elements to a prototype, they should solely consist of methods, constants/enums which are universally accessible to every instance (due to the live reference in .constructor.prototype's value upon instance creation).

And honestly, unless you're focused on intense memory-pool optimization, prior to the introduction of ES6 classes (and obtaining sufficient comprehension --- as they essentially encapsulate .prototype), this may result in more mental exertion than it's worth, and is often (though not always) more effective to construct what you require, or utilize mixins, rather than striving for JavaScript mirroring Java (yet functioning quite differently).

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the best way to integrate a CommonJS module into an ES6 module within a Node.js

I am working on a node app and I want to adopt the ES6 module format without transpiling down to ES5. However, I still want to integrate older libraries like express and socket.io that use CommonJS / require format. What solutions are available for combi ...

Processing incoming requests with a loading interface in CodeIgniter

Is there a way to notify the user who sent the request whether or not the requested user will approve it? Optional: If there is no notification sent to the user who made the request, the requested user will have to wait for verification. For Example: Ima ...

Working with Java to parse non-strict JSON data that does not have keys enclosed in quotes

I am currently facing the challenge of parsing a string in JSON format where keys are not enclosed in quotes. While I have successfully parsed this string in Javascript, I am struggling to find a Java API that can assist me with parsing. The APIs I have at ...

Transform the array by utilizing its own elements

I came up with a solution to a problem I was facing, but I'm not entirely comfortable with it. It feels risky to me, like using an array to redefine itself is not a good coding practice. It's similar to trying to explain a word by using the word ...

The main content will be displayed on the sub-routes of the child

I'm feeling uncertain about the routes for children. For example, I have an 'About' route with 'me' as a sub-route: { path: '/about', name: 'About', component: About, children: [ { ...

AngularJS is capable of dynamically altering the URL based on the specific HTTP method being used, such as

I have implemented Angular factories to connect ajax requests with my web api. Below is an example of how the factory is structured. app.factory('QuestionContainer', ['$resource', function ($resource) { return $resource('http://lo ...

What is the correct method to display a THREE.Line in the correct sequence?

Currently, I am in the process of constructing a model solar system and have been using THREE.Line to create orbits for my planets. Everything seems to be going well until you view the orbits from the front of a planet, revealing that they are actually bei ...

How can you modify the styling of a single child element within a grandparent container and then revert it back to its original state

My goal is for #homeContainer to occupy the entire width of the page, but a higher-level element is restricting its width and margin. Below you can see the DOM structure. By removing margin: 0 auto, I am able to achieve full width. How can I specifically ...

"Encountering difficulties when attempting to assign multiple functions to an onClick event for a button

Here is a sample button code: <Grid item xs={4} sm={12} md={6}> <Button variant="contained" color="success" type="submit" ...

The most secure method for retrieving User Id in AngularFire2

I'm currently facing a dilemma in determining the most secure method to obtain an authenticated user's uid using AngularFire2. There seem to be two viable approaches available, but I am uncertain about which one offers the best security measures ...

Tips for Creating a Website Menu that Stays At the Top of the Page

I have implemented the side menu on my website using this code exactly as described in the tutorial. However, I am unsure how to modify it so that the menu remains fixed at the top of the screen when scrolling. The goal is to eliminate the need to scroll ...

Extract Text from a Div Element or a JavaScript Variable

Presenting my code snippet If the user selects this button <a href="javascript:void(0)" onClick="someFunction()">Copy</a> I want to copy the text within this div. Any suggestions on how I can achieve this? Please excuse any language errors i ...

Detecting collisions in JavaScript

Currently, I am in the process of reviving an old game reminiscent of Tron using HTML5 canvas and JavaScript. The unique twist in this version is that the snakes have the ability to move in curves rather than right angles (known as Achtung Die Kurve). The ...

Vite HMR causes Vue component to exceed the maximum number of recursive updates

After making changes to a nested component in Vue and saving it, I noticed that the Vite HMR kept reloading the component, resulting in a warning from Vue: Maximum recursive updates exceeded... Check out the online demo on stackblitz. Make a change in Chi ...

Is there a way for me to view the output of my TypeScript code in an HTML document?

This is my HTML *all the code has been modified <div class="testCenter"> <h1>{{changed()}}</h1> </div> This is my .ts code I am unsure about the functionality of the changed() function import { Component, OnInit } f ...

The variable is currently undefined because it has an array assigned to it

Upon selecting multiple checkboxes for variants, I am retrieving checked data using the following method: get selectedIdsFromViolCategoriesFormArray(): string[] { return this.violCategories .filter((cat, catIdx) => this.violCategoriesFormArr. ...

Using JavaScript to alter CSS styles with dashes

Currently, I'm delving into the world of manipulating CSS using JavaScript: img.style.borderRadius = "100%"; img.style.border = "9px solid #ffffff"; img.style.boxShadow = "0 0 5px #00000070"; img.style.margin = "20px"; I'm wondering how to chan ...

What is the best way to load the route calculation dynamically?

I am struggling with calculating the Google Maps route dynamically. The console shows an error stating that 'calcularRuta' is not defined: Uncaught ReferenceError: calcularRuta is not defined at HTMLInputElement.onclick (index.html:1) Despi ...

Using jQuery to Hide and Show 3 Divs with Clicked Buttons

My goal is to have three divs, each with different content that will be displayed when a user clicks a corresponding button. I would like the first div to be displayed by default when the page loads. I attempted to achieve this using the code below, but ...

Tips for creating a hover-activated dropdown menu

How can I create a drop-down menu in my horizontal navigation bar that appears when hovering over the Columns tab? The drop-down menu should include options such as Articles, Videos, Interview, and Fashion. To better illustrate what I am looking for, here ...