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

Using jQuery's .grep() method on an array will only return the final digit

Could someone help me understand the behavior of jQuery's .grep() method? I'm creating a jQuery object array based on the names of these elements: <div class="small1 other">S1</div> <div class="small2">S2</div> <div c ...

Can a constructor function be utilized as a parameter type in another function within TypeScript?

Recently, I came across TypeScript and after watching some video reviews, I see great potential in it. It seems to offer better code completion, implicit code documentation, and enhanced type safety for JavaScript. I'm currently in the process of con ...

Is there a way for me to gain entry to this array in vuejs?

Can anyone help me with accessing the objects in this array? I am using laravel, inertiajs, and vuejs. I am passing a variable from a laravel controller to a vuejs component with inertia.js. https://i.stack.imgur.com/p7yjL.png https://i.stack.imgur.com/y ...

Is it possible for (variable or {}) to function seamlessly across all web browsers when using Javascript

When writing code in JavaScript, the if(variable) clause is used to check if a list or array is not null or undefined in order to avoid exceptions. Here's an example: if (list) for (var k in list) { ... if (array) for (var i = array.l ...

anchor text substitution for hyperlink

I currently have a code snippet that replaces a span class with a hyperlink. The hyperlink contains an abbreviation, and the alternate text for the link also includes the same abbreviation. Now, I am looking to replace the second abbreviation in the alte ...

TS2345: The argument provided, which is of type 'Event', cannot be assigned to the parameter expected, which is of type 'HtmlInputEvent'

I am facing an issue while trying to upload a file, and I could use some assistance in resolving it. Angular-----Error: src/app/admin/producto/create-producto-dialog.html:38:47 - error TS2345: Argument of type 'Event' is not assignable to parame ...

Is it possible for jquery.find() to only target immediate children?

How can I use jQuery.find() to specifically target only the direct children of an element without selecting their descendants? Leading the selector with '>' or using '*' doesn't give me the desired result. While I know about jQuer ...

Updating a property on an object during iteration

Currently, I am in the process of developing a Single Page Application using Laravel on the backend and Vue.js. I have two arrays that are crucial to my project: The first array is accessArray: ["BIU","CEO","Finance","HRD","Group"] The second array is a ...

Looking for solutions to manage mouseenter, mouseleave events and ensuring content dropdowns stay visible in Vue.js 2?

Hey there, I'm trying to figure out how to keep dropdown content from disappearing when using @mouseenter and @mouseleave. Here's what I have so far: <div class="wrapper"> <div class="link" @mouseenter="show = ...

Error: Expecting only one React element child to be passed into React.Children.only() function

I am encountering an issue while attempting to construct a web table using the antd library. The exact error message reads: "react.development.js:1251 Uncaught Error: React.Children.only expected to receive a single React element child". I have been stru ...

Automated pagination integrated with automatic refreshing of div every few seconds

I am currently working on setting up a datatable and I need it to be displayed on the monitor in such a way that it can refresh the div and automatically paginate to the next page. However, whenever the div is refreshed, the auto-pagination gets cancelle ...

What is the best way to extract all "conditions" nested under the key "logic" at the 0th index in a JSON object?

I need to manipulate a nested object by removing every "condition" where the key is "logic" and the value is 0 from it. Here is an example of the object structure: Original input: [ { "conditions": [ { "logic": "AND", "paramet ...

transferring data from a web page to a php script seamlessly without navigating away

I've already spent a significant amount of time searching on Stack Overflow and Google, but I haven't found a solution that works for me. My issue is that I have an HTML form and I need to send the data to PHP without redirecting or leaving the ...

When you try to remove an element from an array by its index in Vue JS, the outcome may not be

Here is an array that I have: var hdr = ("name", "date", "start_time", "selling_item", "total_call", "end_time", "ad_num", "area", "order_num"); //this data comes from the database Now, I need to rename these array elements according to prope ...

Is there a reason why angularJS doesn't provide the exact error location directly, opting instead to just offer a link to their website that provides a generic explanation?

Why does AngularJS not provide the specific error location directly, such as which file the error is in, instead of just giving a link to their website with a generic explanation? This makes debugging very challenging! Whenever there is an error, it becom ...

When should the grecaptcha.execute() function be invoked while utilizing Invisible reCAPTCHA V2?

I recently implemented invisible reCAPTCHA successfully, but I'm wondering if I did it correctly when calling grecaptcha.execute(). After loading the API script with an explicit call like this: <script src="https://www.google.com/recaptcha/api.js ...

Retrieve items from an array using a series of nested map operations

When I execute the query below, it transforms the json data into objects - 1st level being a map (This works fine as expected) const customerOptions = () => { return customersQuery.edges.map(({ node: { id, name } }) => { return { key: id, text ...

Error encountered in Express.js blogging app: Issue arises when attempting to filter posts by category, resulting in a "Cast to ObjectId failed" error

Currently, I am developing a blogging application using technologies like Express, EJS, and MongoDB. In the application, I have structured posts into different categories, each stored in its own collection. However, I encountered an issue while attemptin ...

Determine the width of the window and adjust the positioning of jQuery UI tooltips accordingly

Struggling to adjust the jQuery UI tooltip position based on screen width, but can't seem to figure it out. Can someone assist me in detecting the browser's width and changing the tooltip position accordingly? [fiddle] $(function () { $(doc ...

When a table row is selected, set the OnClick attribute of an input to the value of the TD cell in that row based on

I'm really struggling with this. So, here's the issue - I have a table where rows get assigned a class (selected) when clicked on. Now, there's an input inside a form that needs to redirect to another page when clicked, and it also needs t ...