Javascript: Accessing a shared variable within the class

Embarking on my JavaScript programming journey filled me with optimism, but today I encountered a challenge that has left me stumped. Within my tutorial project, there exists a class named Model which contains both private and public variables. Of particular interest is the 'myEvent' variable, of type CustomEvent:

      function Model(){
        /**
         * Array in which the questions are stored
         */
        var questions=new Array();
        var db;
        var valuesSplit="*";
        var tableName="quests";
        this.myEvent=new CustomEvent("my event");

As you can see, "myEvent" is a public variable that can be accessed from external sources. It serves as an event that can be subscribed to by other objects outside the class and can also be triggered internally within the class. However, this is where I encounter a roadblock. How do I access myEvent within the model class itself?

I attempted the following:

    this.myEvent.fire()

and:

    myEvent.fire()

Despite my efforts, I consistently receive the error message "myEvent is not defined."

Answer №1

One important thing to note is that JavaScript does not have traditional classes. It's best to forget about "JavaScript classes" and focus on understanding JavaScript's object-oriented programming (OOP) approach, which involves constructor functions like your Model.

You can access the myEvent property from any code that has a reference to an object created by new Model. This includes code within your constructor function (using this) and any functions called with this pointing to that object. Alternatively, you can access it externally using someObjReference.myEvent.

In JavaScript, the value of this is determined solely by how a function is called, not where it is defined as in some other languages. This difference is discussed further in my blog posts "Mythical methods" and "You must remember this".

Here's a common pattern for setting up constructor functions with shared methods:

function Foo() {
    this.myEvent = new CustomEvent("my event");
}
Foo.prototype.bar = function() {
    this.myEvent.fire();
};

// Usage:
var f = new Foo();
f.bar();          // Fires the event indirectly via `bar`
f.myEvent.fire(); // Fires it directly

Note that calling bar with a different context will result in this not pointing to an instance of Model, leading to errors.

Unlike class-based languages like Java or C#, JavaScript functions are not bound to specific objects. Understanding this flexibility and closures in JavaScript is key to effective coding in the language.

To correctly set the value of this when calling a function, there are two main techniques:

  1. Invoke the function directly from an object property in the same expression:

    var f = new Foo();
    f.bar();    // <== The key bit
    f["bar"](); // <== Also works
    

    By doing this, JavaScript automatically sets this to the object referenced by f during the function call. However, splitting the property retrieval and function invocation will prevent this behavior.

  2. Utilize the call and apply methods of JavaScript function objects to explicitly set the value of this:

    var f = new Foo();
    f.bar(1, 2):       // <== Calls `bar` with `this` === `f` and passing in
                       //     the arguments 1 and 2
    var b = f.bar;
    b.call(f, 1, 2);   // <== Does the same thing as f.bar(1, 2)
    var args = [1, 2];
    b.apply(f, args);  // <== Does the same thing as f.bar(1, 2)
    

    Using call and apply allows explicit control over setting the value of this when invoking a function.

Answer №2

When utilizing myEvent in a non-public function within your Model, you will need to establish an additional reference to myEvent that does not rely on the this reference of your Model. This is necessary because the context of this in another function differs from that in your Model function. One way to address this issue is by creating a new variable in your Model:

var that = this;

Subsequently, you can access myEvent as follows:

that.myEvent

Answer №3

The myEvent property needs to be accessible in both the inner and outer scopes of the object.

function Model(){
    this.myEvent = 'some value';
    this.canAccessEvent = function(){
        return 'myEvent' in this;
    }
}

var m = new Model();
// Accessing from outside: 
alert(m.myEvent);
// Accessing from inside: 
alert('Model can access the event? ' + m.canAccessEvent());

However, there is a possibility that the new CustomEvent function does not exist or does not return a valid object, resulting in the myEvent variable being undefined. It is recommended to assign a different value to the myEvent property and check if it is defined. If it is defined, then the issue may be with your CustomEvent function.

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

Here's a guide on using a button to toggle the display of password value in Angular, allowing users to easily hide

I have successfully implemented an Angular Directive to toggle the visibility of password fields in a form. However, I am facing an issue with updating the text displayed on the button based on the state of the input field. Is there a way for me to dynami ...

Want to easily switch between pictures in the Gallery?

I've created a gallery using jQuery, CSS & HTML and now I want to implement next and previous image buttons. I have added the buttons to the page and written functions for them, but I am struggling with the implementation. Here is my code, if anyone h ...

Encountered a problem when attempting to upload images to Cloudinary through the front-end and save the information in a MySQL database using Axios on Node JS

I am currently working on a web application using React. I have implemented a form where users can input text data and upload multiple image files. The goal is to store the submitted images on Cloudinary along with other text data in a MySQL database. Unf ...

Using jQuery, you can disable an option upon selection and also change its border color

learn HTML code <select name="register-month" id="register-month"> <option value="00">Month</option> <option value="01">January</option> <option value="02">February</option> <option value="03"& ...

Ember - Issue with Page Display

Currently tackling my first ember application, which consists of two pages: the Welcome page and a page displaying student details. To accomplish this, I have established two routes named index and studentdb. Unfortunately, I'm encountering an issue w ...

Javascript - Relocating a file to a different folder in a node.js environment

I am looking to duplicate a file and relocate it within the directory structure. Current file location: Test.zip -> Account/Images/ -account.png -icon.png -flag.png . ...

Tips for enhancing the fluidity of animations after removing an item from a list

I'm working on a project where I have a list of elements that are removed with an animation when clicked. However, I noticed that when one element is removed, the rest of the elements just jump up instead of smoothly transitioning. Is there a way to m ...

Upon its second use, Ajax is loaded with cached data

Imagine a table with multiple rows, each row containing a SHOW button that reveals hidden content when clicked. The hidden div (with the classname "Content") loads the content of a second page using ajax and the id of the corresponding table row. However, ...

Issues with jQuery compatibility when used alongside HTML and CSS

My coding tool is flagging errors in my JavaScript file, including: -'$' usage before definition. -Incorrect spacing between 'function' and '(' This is the content of my JS file: $(document).ready(function() { $(window).s ...

The issue with the autoresize feature in the tinymce plugin arises when trying to delete HTML img content using the backspace

When using the tinymce editor with the autoresize plugin enabled, I have noticed that it works correctly with text. However, there is an issue when inserting HTML content via execCommand. For example, if I insert the following code: <div> < ...

Executing jQuery code after a data update in Angular can be achieved by utilizing

Currently, I am working with Angular 1.4.7 on a site that was not set up by me. As a result, I am uncertain about the specific information needed in this scenario. We are displaying search filters, but their enabling or disabling is controlled by data fetc ...

Utilizing prerender.io with lazy loading in Angular 2: A comprehensive guide

As Angular Universal is not expected to be included in the CLI for some time, I've had to resort to using prerender.io in order to ensure proper SEO functionality. However, my tests have shown that there are issues with lazy loaded modules causing SEO ...

How can you correctly make an Ajax request using computed properties sourced from VueX Store?

Is there a way to make an AJAX call where one of the parameters is a computed State in VueX? For instance, if I use this.$axios.get('someUrl/' + accID ), with accID being a computed property from VueX (using MapState), sometimes it returns ' ...

I am attempting to activate the "about us" button on the website. I have successfully included the path and added a router link to the containing div of the button. However, there seems to be something

In my app, the first step involves specifying the path in the routing module. Following that is defining the home component, then the app component, and finally creating the button using HTML. Setting up the path in the app.routing.module.ts file <div ...

Sending a function in React.js from one functional component to another

I'm facing an issue with my code where I have a function called postaviRutu in the App component that I need to pass to the child component Sidebar. When clicking on an element in Sidebar, I want it to call the postaviRutu function in App. I've a ...

Issue with mobile.changePage() function not executing as expected

I created a basic code that generates a "Splash screen". For storing my data, I am utilizing localstorage. When I first load it, I retrieve data from a URL and I am able to navigate to different pages using $.mobile.changePage(). However, if the data is a ...

Tips for automatically scrolling to the bottom of a div when new data is added

I'm working on a project with a table nested inside a div, and it has some unique styling: #data { overflow-x:hidden; overflow-y:visible; height:500px; } Currently, as the table fills up with data, a vertical scroll bar appears. But I wa ...

The module 'AppModule' is importing an unexpected value 'AppAsideModule'. To resolve this issue, make sure to include an @NgModule annotation

Recently, I attempted to upgrade my Angular project from version 13 to version 17. However, during the process, I encountered an error stating "Unexpected value 'AppAsideModule' imported by the module 'AppModule'. Please add an @NgModul ...

Using Node.js to handle reading files and dealing with undefined or null values

The get method is responsible for receiving a userid with an initial total number of points defined in the stcok.json file, along with various transactions stored in another file. Below are some sample entries from the stock JSON: [ { "user" ...

Scrolling to an id element in Vue.js can be achieved by passing the ID in the URL using the "?" parameter. This

My challenge involves a URL http://localhost:8080/?london that needs to load directly to the element with an id of london in the HTML section <section id="london"> on the page. Using http://localhost:8080/#london is not an option, even though it woul ...