1

I'd like to get a value of id attribute for an input tag.

<input type="text" id="heading1" class="alert-heading" value="aaa" />

In order to to this, I wrote this code.

var alertHeading = $(".alert-heading");

alertHeading.on('blur', function(){
    var headingId = $(this).attr("id");
    console.log(headingId); // outputs 2943. I'm expecting "heading1".
});

But, I get a weird number when I get an access to id although I'm expecting to get a "heading1".

This is the code that I'm working on right now.

var alertHeading = $(".alert-heading");

alertHeading.on('blur', function(){

    var key = alertMode.val();

    chrome.runtime.getBackgroundPage(function(backgroundPage) {

        var background = backgroundPage.background;

        var alertObject = background.getStorage(key);

        //(EDITED)Oh I think $(this)here no longer points to the input element!!
        var headingId = $(this).attr("id");

        console.log(headingId); // outputs 2943. I'm expecting "heading1".

    });

})

Please help me out to solve this problem. Thanks in advance!

crzyonez777
  • 1,789
  • 4
  • 18
  • 27

2 Answers2

3

Explaining this in ECMAScript terms, every time control enters a function a new Execution Context is created. Each execution context has its own thisBinding, hence you need to store a reference to the outer context's this reference so that you can access it through lexical scope.

alertHeading.on('blur', function(){
    //[...]
    var el = this; //copy the `this` reference to a variable
    chrome.runtime.getBackgroundPage(function(backgroundPage) {
        // [...]
        var headingId = el.id; //access outer scope's this

    });
});

I'm using el.id which access the id property of the DOM element referenced by el. It is good practice to work with the DOM instead of HTML attributes whenever you can.


The lexical scope trick is the most common approach but there are several ways to fix this.

In ES5, it is also possible to .bind() the this reference of a function object:

alertHeading.on('blur', function(){
    chrome.runtime.getBackgroundPage(function(backgroundPage) {
        // [...]
        var headingId = this.id; //2. Now it has the same this as outer scope

    }.bind(this)); //1. The onblur's `this` is bound to the bgpage callback
});
Community
  • 1
  • 1
Fabrício Matté
  • 69,329
  • 26
  • 129
  • 166
2

You need to save this in a closure variable:

alertHeading.on('blur', function(){

    var key = alertMode.val();
    var that = this;

    chrome.runtime.getBackgroundPage(function(backgroundPage) {
        var background = backgroundPage.background;
        var alertObject = background.getStorage(key);
        var headingId = that.id;
        console.log(headingId);
    });
});
Barmar
  • 741,623
  • 53
  • 500
  • 612