简体   繁体   English

如何在函数中的javascript中创建2` this`引用

[英]How to create 2 `this` reference in javascript from within a function

I have issues getting my code to work as I try to break it down into smaller methods because of the this referencing. 我有问题让我的代码工作,因为我试图将其分解为更小的方法因为this引用。 My code is as follow: 我的代码如下:

const pageObject = {

    /* set listener to get id of the radio input and then do something with it*/
    onChange() {

        // `this` here refers to the pageObject
        console.log(this);

        $('.radio input[type="radio"]').on('click', function() {

              // `this` here refers to the radio input
              console.log(this);

              let $id = $(this).data('id');

              // Error because `this` is referencing the radio input and not the pageObject.
              this.doSomething($id); 
        }

    },

    /* just does something */
    doSomething($id) {
        return ... 
    }

}

// just calls the method on object so we can get started
pageObject.onChange();

I also want to avoid using es6's arrow-functions () => and self = this techniques if possible as recommended in YDKJS: This & Object Prototypes . 我还想避免使用es6的arrow-functions () =>self = this技术,如果可能的话,如YDKJS:This&Object Prototypes中推荐的那样

Is there a way to .bind()/.call()/.apply() the method onChange() to reference the this which references to the pageObj and also the this which references to the radio input? 有没有一种方法来.bind()/.call()/.apply()方法onChange()引用this到哪个引用pageObj ,也是this其中引用收音机输入?

Feel free to rearrange the code if necessary. 如有必要,请随意重新安排代码。 Thanks, looking forward! 谢谢,期待!

Update 更新

Thanks to event.target as suggested below, here is a working code block: 感谢下面建议的event.target ,这是一个有效的代码块:

const pageObject = {

    /* set listener to get id of the radio input and then do something with it*/
    onChange() {

        // `this` here refers to the pageObject
        console.log(this);

       let radioHandler = function radioHandler(event) {

              // `this` here also refers to the pageObject too since we are about to call this function via .bind()
              console.log(this);

              // use event.target here instead. sweet stuff.
              let $id = $(event.target).data('id');

              // doSomething() now works!
              this.doSomething($id); 
        }

        $('.radio input[type="radio"]').on('click', radioHandler.bind(this));

    },

    /* just does something */
    doSomething($id) {
        return ... 
    }

}

// just calls the method on object so we can get started
pageObject.onChange();

Update 2 更新2

How to access the correct this inside a callback? 如何访问正确的this回调里面? as suggested by @gyre in the comments below provides a great detail of how to control this but doesn't mention event.target at all. 正如@gyre在下面的评论中所提出的,提供了如何控制this详细信息,但根本没有提到event.target Anyway, here is MDN Docs on Event.target 无论如何,这里是Event.target上的MDN Docs

You can use event.target or event.currentTarget to reference element event is dispatched to. 您可以使用event.targetevent.currentTarget来调用元素事件。 javascript is also missing closing ) at .on() call. javascript还缺少一个右).on()调用。

$('.radio input[type="radio"]').on('click', function(event) {

  // `this` here refers to the radio input
  let $id = $(event.target).data('radioId');

  // Error because `this` is referencing the radio input and not the pageObject.
  this.doSomething($id); 
})

Just go old style and set it to something else. 只需转换旧样式并将其设置为其他内容。

const pageObject = {

    /* set listener to get id of the radio input and then do something with it*/
    onChange() {

        // `this` here refers to the pageObject
        console.log(this);
        const self = this;

        $('.radio input[type="radio"]').on('click', function() {

              // `this` here refers to the radio input
              console.log(this);

              let $id = $(this).data('id');

              // Error because `this` is referencing the radio input and not the pageObject.
              self.doSomething($id); 
        };

    },

    /* just does something */
    doSomething($id) {
        return ... 
    }

}

// just calls the method on object so we can get started
pageObject.onChange();

In that particular case you don't need to use this inside the event handler by the way, you can have an event parameter and use event.target , like: 在那种特殊情况下,你不需要在事件处理程序中使用this ,你可以有一个事件参数并使用event.target ,如:

const pageObject = {

    /* set listener to get id of the radio input and then do something with it*/
    onChange() {

        // `this` here refers to the pageObject
        console.log(this);

        $('.radio input[type="radio"]').on('click', (event) => {

              // `this` here refers to the radio input
              console.log(event.target);

              let $id = $(event.target).data('id');

              // Error because `this` is referencing the radio input and not the pageObject.
              this.doSomething($id); 
        };

    },

    /* just does something */
    doSomething($id) {
        return ... 
    }

}

// just calls the method on object so we can get started
pageObject.onChange();

Even further... 更深入...

const pageObject = {

    /* set listener to get id of the radio input and then do something with it*/
    onChange() {

        // `this` here refers to the pageObject
        console.log(this);

        $('.radio input[type="radio"]').on('click', this.onRadioClick.bind(this)) ;

    },

    onRadioClick(event) {

            // `this` here refers to the radio input
            console.log(event.target);

            let $id = $(event.target).data('id');

            // Error because `this` is referencing the radio input and not the pageObject.
            this.doSomething($id); 
    },

    /* just does something */
    doSomething($id) {
        return ... 
    }

}

// just calls the method on object so we can get started
pageObject.onChange();

You'll come across this and similar issues pretty often. 你会经常遇到这个和类似的问题。 Depending on the need, I solve it in one of two ways: using closures or binding. 根据需要,我可以通过两种方式解决它:使用闭包或绑定。

Using closures works well in cases like yours here where you're setting an event and defining the event handler in the same parent function. 使用闭包在像你这样的情况下工作得很好,你在这里设置一个事件并在同一个父函数中定义事件处理程序。 You can take advantage of the fact the the child functions can access parent function variables and access a masked form of this 您可以利用子函数可以访问父函数变量并访问屏蔽形式的事实

const pageObject = {

    /* set listener to get id of the radio input and then do something with it*/
    onChange() {

        const parent = this
        // 'parent and `this` here both refer to the pageObject
        // 'parent' masks an instance of 'this' which can be accessed via closures
        console.log('parent, this: ', parent, this);

        $('.radio input[type="radio"]').on('click', function() {

            // `this` here refers to the radio input
            console.log(this);

            let $id = $(this).data('id');

            // 'parent' accesses parent 'this' thanks to closures and masking 
            parent.doSomething($id); 
        }

    },

    /* just does something */
    doSomething($id) {
        return ... 
    }

}

// just calls the method on object so we can get started
pageObject.onChange();

Another method uses bind. 另一种方法使用bind。 This is particularly useful when you want to set an eventListener in one function that calls a handler function defined elsewhere but need information from the 'this' context of the function setting the listener. 当你想在一个函数中设置一个eventListener来调用在别处定义的处理函数但需要来自设置监听器的函数的'this'上下文的信息时,这个特别有用。 It you can use it to break down your code into even small functions. 您可以使用它将代码分解为甚至小功能。

An example using your example could look something like this: 使用您的示例的示例可能如下所示:

const pageObject = {

    /* set listener to get id of the radio input and then do something with it*/
    onChange() {

        // `this` refers to the pageObject
        console.log(this);

        // creates radio onClick eventListener
        // assigns handleRadio function as event handler
        // binds pageObject 'this' context for use in event handler
        $('.radio input[type="radio"]').on('click', this.handleRadio).bind(this);
    },

    // separated event handler function to show how this works in more modular code.
    handleRadio(e) {
        // use e.target to give you the context for the click event
        // use 'this' to access the pageObject 'this' context
        console.log('e.target, this: ', e.target, this);

        // still accesses pageObject 'this' due to the eventListener bind
        let $id = $(this).data('id');

        // No error
        this.doSomething($id); 
    },

/* just does something */
doSomething($id) {
    return ... 
}

}

// just calls the method on object so we can get started
pageObject.onChange();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM