The problem of using jQuery $(this) in ES6

Posted by renegade33 on Sat, 11 May 2019 02:12:17 +0200

$('.js-bottom-btn').click((event) => {
    let flag = $(event.currentTarget).date('flag');
    ...
})

Turn 1

The transition to laravel-mix ES6 started in the old project. The meaning of $(this) in the arrow function when used with jQuery has changed.

 

The main reason for this problem is that it is not clear. Arrow function:

$('.js-bottom-btn').click(() => {
    let flag = $(this).date('flag');
    ...
});

Conversion to:

$('.js-bottom-btn').click(function() {
    let flag = $(_this).date('flag');
    ...
});

_this is undefined

According to jQuery click document It may be amended to read:

$('.js-bottom-btn').click(event => {
    let flag = $(event.currentTarget).date('flag');
    ...
});

perhaps

 

 

Similar questions:

$('jquery-selector').each(() => {
    $(this).click();
})

Need to be changed to:

$('jquery-selector').each((index, element) => {
    $(element).click();
})

Reference:

 

 

Turn 2

Preface

When using jquery in es6, it's customary to use es5 to get dom elements directly, such as $('selector'), bind click or hover events; if you're following the trend, use arrow functions to define selector events, and use $(this), you'll have a little trouble like me.

Problem recurrence

$('[data-action="imgQRCodeCtrl"]')
        .hover(() => {
            !Base.browser.mobile && $(this).find('.qr-code').css({
                'height': ( $(this).find('.img').height() + 2 ) + 'px',
                'opacity': 1,
                'z-index': 1
            });
        }, () => {
            $(this).find('.qr-code').css({'opacity': 0, 'z-index': -1});
        })
        .click(() => {
            if(Base.browser.mobile){
                location.href = $(this).data('href');
            }
        });

At first glance, this code is not a problem, and the logic is simple. It binds the hover and click events on the list elements with data-action="imgQRCodeCtrl" of all attributes. It can display or hide a block inside the hover on the pc side, and it can get the href on the current attributes and jump when the mobile side clicks.

Of course, so easy, there are no problems in writing this logic on es5 in the past; but after parsing in ES6, there are problems.

The following is the parsed code loaded on the real browser:

var $ = __webpack_require__("./node_modules/jquery/dist/jquery.js");
$(function () {
    var _this = this;
    //....
    $('[data-action="imgQRCodeCtrl"]').hover(function () {
        !_base2.default.browser.mobile && $(_this).find('.qr-code').css({
            'height': $(_this).find('.img').height() + 2 + 'px',
            'opacity': 1,
            'z-index': 1
        });
    }, function () {
        $(_this).find('.qr-code').css({ 'opacity': 0, 'z-index': -1 });
    }).click(function () {
        if(_base2.default.browser.mobile){
            location.href = $(_this).data('href');
        }
    });
});

Look what happened to this! God, this is redefined!

Even if you don't actually run this code, it's a bit basic, and you should be able to anticipate what's going on on the page...

Cause analysis

The following is Daniel's interpretation on Stack Overflow:

This has nothing to do with Traceur and turning something off, this is simply how ES6 works. It's the specific functionality you're asking for by using => instead of function () { }.

If you want to write ES6, you need to write ES6 all the time, you can't switch in and out of it on certain lines of code, and you definitely cannot suppress or alter the way => works. Even if you could, you would just wind up with some bizarre version of JavaScript that only you understand and which would never work correctly outside of your customized Traceur, which definitely isn't the point of Traceur.

The main idea I understand is that "the way ES6 works is like this, it has nothing to do with compilation, it has nothing to do with writing; if you want to use ES6, you'd better use all the way ES6 is written, and you can't change its original definition..." (English is not good, welcome God to correct > <)

Seeing this, I was frightened to look up the documents.

The original arrow function, do not bind their own this, this will make sense; take a good look at the following sentence, do not encounter problems, always vague memory, haha.

The grammar of the arrow function expression is shorter than that of the function expression, and it does not bind its own this, arguments, super or new.target. These function expressions are most suitable for non-Method functions, and they cannot be used as constructors.

Problem solving

  • Method 1: After clearing the principle, it is very simple. The function bound to this does not use the arrow function. The following experiments are sure to be ok:
$('[data-action="imgQRCodeCtrl"]')
        //...
        .click(function() {
            if (Base.browser.mobile) {
                location.href = $(this).data('href');
            }
        });
  • Method 2: Instead of using this, use event. current Target
$('[data-action="imgQRCodeCtrl"]')
        //...
        .click((event) => {
            if (Base.browser.mobile) {
                location.href = $(event.currentTarget).data('href');
            }
        });
  • Method 3: Use the each function to bind to each small element iteratively, so there is no need for this
$('[data-action="imgQRCodeCtrl"]').each((index, element) => {
        let _this = element;
        $(_this).click(() => {
                if (Base.browser.mobile) {
                    location.href = $(_this).data('href');
                }
            });
    });

summary

The above solutions can achieve the desired results, but it is proposed to use method one to solve, more simple and straightforward, in the maintenance and teamwork will play a great role, because no one would like to read other people's written code that turns eighteen corners....

It's a small problem. Maybe some Daniels will despise me when they see it, but they like the feeling of solving problems step by step and explaining them perfectly.

Still on the way, if you have any questions, you are welcome to exchange and correct them. In the future, you will sum up more in this way.

Reference link
https://stackoverflow.com/questions/27670401/using-jquery-this-with-es6-arrow-functions-lexical-this-binding

The original blog link, welcome to stamp:
http://blog.oulafen.com/2017/11/22/es6-jq-this

Topics: Front-end JQuery Mobile Laravel Javascript