Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JavaScript strict mode - "this is undefined" when extending jQuery widget's property

Below are exactly the same pieces of code but one is in strict mode and another isn't.

Here it works:

( function ( $ ) {

    $.widget( 'ui.myWidget', $.ui.dialog, {
        // Here this is defined and successfully overwritten.
        options: $.extend( this.options, {
            someProperty: 'someValue'
        } ),
        _init: function() {
            console.log(this); // Here this is also defined.
        }
    });

} )( jQuery );

Here it doesn't work:

( function ( $ ) {

    'use strict';

    $.widget( 'ui.myWidget', $.ui.dialog, {
        // Here it says "Uncaught TypeError: Cannot read property 'options' of undefined"
        options: $.extend( this.options, {
            someProperty: 'someValue'
        } ),
        _init: function() {
            console.log(this); // Here this is defined.
        }
    });

} )( jQuery );

I've read this: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions_and_function_scope/Strict_mode but still nothing comes to my mind. I just need a little hint and I'll be able to resolve this on my own.

Does anyone have any idea why it may be not working in strict mode?

I don't know if the original $.ui.dialog has options property because I'm extending a completely custom widget that has such property and the above code is just a made up example. I hope that it pictures this well. If it doesn't please request more information and I'll update the question.

like image 682
Jimsea Avatar asked Feb 07 '26 14:02

Jimsea


1 Answers

That expression, this.options, is evaluated in the context of your outer function:

(function( $ ) {
  // ...
} )( jQuery );

That function is called with a plain, "naked" function call, and so in strict mode the value of this is undefined.

Looking more closely at the key portion of the code:

$.widget( 'ui.myWidget', $.ui.dialog, {
    // Here it says "Uncaught TypeError: Cannot read property 'options' of undefined"
    options: $.extend( this.options, {
        someProperty: 'someValue'
    } ),
    _init: function() {
        console.log(this); // Here this is defined.
    }
});

The expression this.options looks like it's buried in the middle of a lot of stuff, but in reality it's going to have to be evaluated before $.widget() is ever called, and before $.extend() is called to get a value for that "options" property.

  • Before calling $.widget(), the runtime has to evaluate all its parameters. Thus, it's got to completely build the object from that object literal.
  • To build the object literal, it has to evaluate the property values. That means it has to call $.extend().
  • To call $.extend(), it has to evaluate the arguments.
  • this.options is one of the arguments to $.extend(), but this is undefined. Boom.
like image 171
Pointy Avatar answered Feb 09 '26 10:02

Pointy



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!