When an array is prototyped as a member of a JavaScript object, it becomes a shared property among all instances

Is anyone else surprised by this behavior? It really caught me off guard... I was expecting prototyped arrays to be private to each instance of a class rather than shared across all instances.

Can someone confirm if this is the intended behavior and provide a more detailed explanation?

Take note of the commented code and how it impacts the script's behavior.

<html>
<head>

<script type="text/javascript">

function print_r( title, object ) {

    var output = '';
    for( var key in object ) {

        output += key + ": " + object[ key ] + "\n";

    }

    output = title + "\n\n" + output;

    alert( output );

}

function Sandwich() {

    // Uncomment this to fix the problem
    //this.ingredients = [];

}

Sandwich.prototype = {

    "ingredients" : [],
    "addIngredients" : function( ingArray ) {

        for( var key in ingArray ) {

            this.addIngredient( ingArray[ key ] );

        }

    },
    "addIngredient" : function( thing ) {

        this.ingredients.push( thing );

    }

}

var cheeseburger = new Sandwich();
cheeseburger.addIngredients( [ "burger", "cheese" ] );

var blt = new Sandwich();
blt.addIngredients( [ "bacon", "lettuce", "tomato" ] );

var spicy_chicken_sandwich = new Sandwich();
spicy_chicken_sandwich.addIngredients( [ "spicy chicken pattie", "lettuce", "tomato", "honey dijon mayo", "love" ] );

var onLoad = function() {

    print_r( "Cheeseburger contains:", cheeseburger.ingredients );

};

</script>

</head>
<body onload="onLoad();">
</body>
</html>

Thank you in advance!

Answer №1

Objects in JavaScript work with a prototype system where properties are shared among objects that inherit from the same prototype. This means when creating new instances from a "class" (which doesn't truly exist in JS), they all reference the same set of properties.

However, how you interact with these inherited properties can vary:

function Foo() {}

Foo.prototype = {
    array: [],
    func: function() {}
}

a = new Foo();
b = new Foo();

a.array.push('bar');
console.log(b.array); // prints ["bar"]

b.func.bar = 'baz';
console.log(a.func.bar); // prints baz

In all cases, you're modifying the same object.

But if you assign a value to a property, it creates an instance-specific property rather than changing the shared prototype:

console.log(a.hasOwnProperty('array')); // prints false
console.log(a.array); // prints ["bar"]
a.array = ['foo'];
console.log(a.hasOwnProperty('array')); // prints true
console.log(a.array); // prints ["foo"]
console.log(b.array); // prints ["bar"]

If you want each instance to have its own array, define it within the constructor:

function Foo() {
    this.array = [];
}

Using this inside the constructor ensures that data is specific to each instance while shared methods should be assigned to the prototype.


For further insights, check out Details of the object model which explains the differences between class-based and prototype-based languages.

Update:

You can access an object's prototype using Object.getPrototypeOf(obj) (may not work in older browsers), where

Object.getPrototypeOf(a) === Object.getPrototypeOf(b)
would return true, indicating both point to the same underlying object - the Foo.prototype.

Answer №2

The action is accurate. [] is converted to new Array() during execution, however, only a single array of this nature is generated.

To put it differently, Obj.prototype = {...} is processed in the same manner as any standard assignment.

Answer №3

Creating a new instance of an object in JavaScript using the var exp1 = new C() syntax results in setting exp1.[[Prototype]] = C.prototype. This means that properties accessed on the instance are first checked on the object itself, and if not found, it looks in the [[Prototype]] chain. Essentially, any definitions made in the prototype are shared among all instances, allowing changes to the prototype to reflect across all existing instances.

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

Problem encountered with sorting single and double digit numbers using NSSortDescriptor

I recently encountered a challenge while sorting my array based on experience. The code I used for sorting looked like this: sortexp = [NSSortDescriptor sortDescriptorWithKey: @"Experience" ascending:YES]; arrData = [arrData sortedArrayUsingDescriptors: ...

the final value in a pandas dataframe

In this code snippet, I have successfully accessed the max() value in the array. However, my goal now is to access the last value of the dataframe. How can I accomplish this task? 'horizontal': round(df[['x2', 'x3']].max().max ...

Assign the Firebase token to the JavaScript cookie value

Can a cookie store a token value? In my setup with js-cookie, Firebase auth/firestore, and Next.js, I am setting my cookie within the handleUser function like this: const handleUser = async (rawUser) => { if (rawUser) { const user = await fo ...

Trying to assign a value to a property that is not defined

I'm attempting to initiate the loading and exhibition of a .stl file through three.js by implementing the following code: var stlLoader = new THREE.STLLoader(); stlLoader.load('assets/Cap.stl', function (object){ object.position.y = - 1 ...

Are you interested in using jQuery and/or AJAX to retrieve the latest images from a website?

I had to utilize a Wikipedia API in order to retrieve images from the New Jersey website, and I devised two methods to carry out similar tasks. The initial approach involved using JSON, but it ended up pulling the entire page content. <script type="tex ...

Remove the class upon clicking

I recently created a toggle-menu for my website that includes some cool effects on the hamburger menu icon. The issue I am facing is that I added a JavaScript function to add a "close" class when clicking on the menu icon, transforming it into an "X". Whil ...

What is the process to retrieve the username from my system and display it in a web browser?

Seeking assistance to retrieve my system's username and display it on a web browser. Currently, I have been using ActiveXObject method, which successfully retrieves the username, but has drawbacks such as requiring ActiveX to be enabled and only works ...

Unable to locate additional elements following javascript append utilizing Chrome WebDriver

I have a simple HTML code generated from a C# dotnet core ASP application. I am working on a webdriver test to count the number of input boxes inside the colorList div. Initially, the count is two which is correct, but when I click the button labeled "+", ...

The Great Gatsby - Unable to access property 'component---src-pages-index-jsx' due to its undefined nature

Attempting to transition my current ReactJS application with a WordPress backend to GatsbyJS has presented some challenges. As a newcomer to GatsbyJS, I diligently followed the setup instructions provided on their website for Windows 10. Despite a successf ...

What is the reason for the absence of Duplex Stream in the Web Streams API?

I have experience working with the traditional nodejs stream, which makes the need for Duplex streams quite evident. These are streams that can both read and write data, like net.Socket. As mentioned here Examples of Duplex streams include: TCP sockets ...

Limit the elements in an array within a specified range of dates

Currently, I am working on implementing a filter functionality for a data array used in a LineChart within my Angular application using TypeScript. The structure of the data array is as follows: var multi = [ { "name": "test1", "series": [ ...

Ways to retrieve the date of the chosen <td> cell in a calendar

Looking for a way to extract dates from the <td> elements selected by mouse? Here is my code snippet that highlights the TD upon selection: $(function () { var isMouseDown = false, isHighlighted; $("#schichtplan td") .moused ...

Determine the outcome of the assessment quiz

Greetings everyone, I apologize for my poor English. I've been searching through numerous documents, but due to my language barrier, I am having trouble understanding them. I have designed a quiz page, but I'm facing an issue where I can't d ...

Could Ramda assist in enhancing pipeline/composition processes with a logging feature?

Considering implementing logging within a composed chain of functions, the following code demonstrates how it can be achieved: const f = R.compose( transformation2, doAlso(x => console.log(`id: ${x.id}`)), transformation1 ) This approach would c ...

Automatically relaunch NodeJS application upon app failure

I am looking for a way to automatically restart my NodeJS (Express) app after crashes with errors. I am familiar with the forever npm package, but all the examples I found were for running the app in development. My goal is to implement this in production ...

Steps to efficiently enumerate the array of parameters in the NextJS router:

In my NextJS application, I have implemented a catch all route that uses the following code: import { useRouter} from 'next/router' This code snippet retrieves all the parameters from the URL path: const { params = [] } = router.query When I co ...

Disable form input fields while keeping all other elements enabled

Currently, I am facing a dilemma where I must deactivate specific input fields within a form. Given that there are numerous fields to consider, individually disabling each one seems impractical. Can anyone offer advice on how to disable a set of elements ...

Tips on preventing further input in this code - a script designed to take in a 1D array of undetermined length

I am struggling to figure out how to stop the input in my code. I have created a code that takes input from an array with integer elements. When a non-integer element is inputted, it gets ignored. However, I am unable to find a way to stop the input proces ...

Tips for applying various CSS properties to a single element using styled-components

Is there a way to style similar elements differently using different CSS properties in styled components? For example: <div></div> <div></div> With the knowledge I have, I can do: export const StyledDiv = styled.div` color: red; ` ...

Unleashing the power of eventListeners through exponential re-rendering upon state updates

Trying to implement an eventListener for "keydown" to update the state (a boolean named showMenu). I placed it inside a useEffect, but it's not functioning correctly and I can't pinpoint the issue. When I include showMenu in the dependency arra ...