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

如何从函数中创建javascript中的2`this`引用,javascript,jquery,ecmascript-6,this,Javascript,Jquery,Ecmascript 6,This,由于这个引用,我在尝试将代码分解为更小的方法时遇到了问题,无法让代码正常工作。我的代码如下: 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 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();
我还希望尽可能避免使用es6的箭头函数
()=>
self=this
技术,如中所建议

有没有办法
.bind()/.call()/.apply()
方法
onChange()
来引用
this
,它引用了
pageObj
,还有
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);

       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();
更新2


正如@gyre在下面的评论中所建议的那样,它提供了如何控制
的详细信息,但根本没有提到
事件。target
。无论如何,这里是您可以使用
event.target
event.currentTarget
引用元素事件
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); 
})

就换成老式的,换成别的

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(); 更进一步

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(); 常量页面对象={ /*将侦听器设置为获取无线电输入的id,然后对其进行处理*/ onChange(){ //“this”在这里指的是页面对象 console.log(this); $('.radio输入[type=“radio”]')。on('click',this.onRadioClick.bind(this)); }, onRadioClick(事件){ //‘this’这里指的是无线电输入 console.log(event.target); 让$id=$(event.target).data('id'); //错误,因为“this”引用的是无线电输入,而不是页面对象。 这个。doSomething($id); }, /*只是做点什么*/ doSomething($id){ 返回。。。 } } //只要调用对象上的方法,我们就可以开始了 pageObject.onChange();
你会经常遇到这样或类似的问题。根据需要,我用两种方法之一解决它:使用闭包或绑定

使用闭包可以很好地处理像您在这里设置事件并在同一父函数中定义事件处理程序的情况。您可以利用子函数可以访问父函数变量的事实,并访问该变量的屏蔽形式

另一种方法使用bind。当您希望在一个函数中设置eventListener,该函数调用在别处定义的处理程序函数,但需要来自设置侦听器的函数的“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();

可能是重复的感谢,这帮我指明了正确的方向。尽管此代码仍然会导致错误,因为它仍然指向无线电输入。我已更新了我的问题以包含工作答案。您可以将
传递到
。on()
,在处理程序内部使用
事件。数据
引用
页面对象
。on(“单击”,{pageObject:this},函数(事件){console.log(event.data.pageObject)}
。您可以发布并接受自己的答案。此处的“更进一步…”代码也是此问题的有效答案,因为它是一个完整的答案,并且不使用问题中所述的es6双箭头功能。标记为答案!闭包方法与尝试设置词法
this
相同。我个人将坚持使用
.bind()
,如中所述:“虽然self=this和arrow函数似乎都是不想使用bind(..)的好“解决方案”,但它们实际上是在逃避,而不是理解和接受它。”。但是,这也可能是一个偏好和一致性的问题,所以。。。回答得很好,谢谢!
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();
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();