jquery

Overriding jQuery .val() function works but getter is called multiple times


I'm overriding jQuery's .val() function so that when I set the value of my select element I can automatically trigger the change event.

The getter and setter code works fine, however when doing $('select').val() the console outputs Getter two times. I don't believe that's supposed to happen, so does anyone know what's wrong?

Here's a jsfiddle: https://jsfiddle.net/41hxsam9/1/

const originalVal = $.fn.val;

$.fn.extend( {
    val: function() {
        if ( arguments.length > 0 ) {
            if ( this.hasClass( 'myselect' ) ) {
                console.log( 'Setter' );
                const result = originalVal.apply( this, arguments );
                this.trigger( 'change' );
                return result;
            }
        }
        console.log( 'Getter' );
        return originalVal.apply( this, arguments );
    }
} );

Solution

  • If we log the object the val is returning, we see that it is called once for the select and once for the option - that is likely just how jQuery works:

    else {
      // Getter call.
      console.log('Getter',this["0"]);
      return originalVal.apply(this, arguments);
    }
    

    $(() => {
    
    const originalVal = $.fn.val;
    $.fn.extend({
      val: function() {
        if (arguments.length > 0) {
          // This is a setter call.
          if ($(this).hasClass('myselect')) {
            console.log('Setter');
            const result = originalVal.apply(this, arguments);
            $(this).trigger('change');
            return result;
          } else {
            // Normal setter for elements without the class.
            return originalVal.apply(this, arguments);
          }
        } else {
          // Getter call.
          console.log('Getter',this["0"]);
          return originalVal.apply(this, arguments);
        }
      }
    });
    
    $('#button-1').click((e) => {
      $('select').val('1');
    });
    
    $('#button-2').click((e) => {
      console.log($('select').val());
    });
    });
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
    <p>
      <button id="button-1">Set Value</button> <button id="button-2">Get Value</button>
    </p>
    <p>
      <select class="myselect">
        <option value="1">Option 1</option>
        <option value="2">Option 2</option>
        <option value="3">Option 3</option>
      </select>
    </p>