【问题标题】:'this' does not work properly in another event. I'm clueless as to why [duplicate]'this' 在另一个事件中无法正常工作。我不知道为什么[重复]
【发布时间】:2024-01-02 12:16:01
【问题描述】:

简短的故事,我不知道为什么它不起作用,我尝试过 Console.Log() 来弄清楚“this”是什么,而事件只是不断地传递窗口。这是一个点击事件,假设在这个轮播中激活对某个人物的影响,这就是为什么我不能单独搜索类(至少据我所知)。聪明人有什么解决办法吗?

var carFigure = null;
//----------The Events
$('.figure').click(toggleCarousel(this));
//$('.figure').mouseover(stopCarousel(this));
//$('.figure').mouseleave(startCarousel(carFigure));

//------------Switcharoo function
function toggleCarousel(event) {
    var bool = false;
    console.log(event)
    if (bool) {
        stopCarousel(event);
        bool = false;
    }
    else {
        startCarousel(event);
        bool = true;
    }
}


//----------The action functions
function stopCarousel(e) {
if (carFigure != null) { document.getElementById('carousel').style.animationPlayState = "paused";
        var p = e.parentElement;
        var a = p.getElementsByTagName('DIV')[2];
        if (a.getElementsByTagName('IMG')[0].style.transform = "none") {
            a.getElementsByTagName('IMG')[0].style.transform = "scale(1.2, 1.2) translateY(-25%)";
            a.getElementsByTagName('IMG')[0].style.borderRadius = "100%";
            a.getElementsByTagName('H5')[0].style.color = "rgba(255,255,255, 0)";
            this.getElementsByClassName('links')[0].style.transform = "translateY(-250%)";
            this.getElementsByClassName('links')[0].style.opacity = "1";
            carFigure = null;
        }
    }
};
function startCarousel(e) {
    if (e != null) {
        carFigure = e;
        document.getElementById('carousel').style.animationPlayState = "running";
        var p = e.parentElement;
        var a = p.getElementsByTagName('DIV')[2];
        a.getElementsByTagName('IMG')[0].style.transform = "none";
        a.getElementsByTagName('IMG')[0].style.borderRadius = "0";
        a.getElementsByTagName('H5')[0].style.color = "rgba(255,255,255, 1)";
        this.getElementsByClassName('links')[0].style.transform = "none";
        this.getElementsByClassName('links')[0].style.opacity = "0";
    }
};
--HTML Version (Snippet)
<div class="carcontainer">
    <div id="carousel">
        <figure>
            <div class="figure">
                <div class="links">
                    <a><img src="~/Content/images/LinkedInIco.png" /></a>
                    <a href="http://www.example.com"><img src="~/Content/images/WebsiteIco.png" /></a>
                </div>
            </div>
            <div>
                <h5>Person Name</h5>
                <img src="~/Content/images/Name.jpg" alt="" />
            </div>
        </figure>
        <figure>
            <div class="figure">
                <div class="links">
                    <a><img src="~/Content/images/LinkedInIco.png" /></a>
                    <a href="http://www.example.com"><img src="~/Content/images/WebsiteIco.png" /></a>
                </div>
            </div>
            <div>
                <h5>Person Name</h5>
                <img src="~/Content/images/Name.jpg" alt="" />
            </div>
        </figure>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

【问题讨论】:

  • 请发布将这些函数绑定到其事件处理程序的代码。
  • 如果您不发布相关的 HTML(.figure 是什么),我们帮不了您。
  • 我不得不调整一个 sn-p 但它是为你发布的。感谢您查看此内容。
  • foo(bar()) 总是首先调用bar() 并将其返回值传递给foo()。查看$('.figure').click(toggleCarousel(this));,很明显这是错误的,因为toggleCarousel 不返回函数,但.click 期望返回函数。注释掉的行也有同样的问题。您显然正在将全局对象传递给此处的函数。
  • 如果您不介意我问:您期望toggleCarousel(this) 中的this 的值是多少? toggleCarousel 需要一个 event 对象。是否认为this 会指代一个事件?如果有,为什么?

标签: javascript jquery events this


【解决方案1】:

您没有正确附加事件处理程序。这一行:

$('.figure').click(toggleCarousel(this));

...调用toggleCarouselthis 立即(这就是parens 会做的)。您真正想要的是将函数对象传递给.click()

$('.figure').click(toggleCarousel);

更新

正如@FelixKling 所指出的,您还需要将事件的目标传递给下游函数;看起来他们期待一个元素,而不是事件。另外,bool 每次调用都会被重置为false,这不是你想要的;你应该把它放在闭包里:

var flag = false; // "bool" is a reserved word, changed the name
function toggleCarousel(event) {
    var element = event.target;
    if (flag) {
        stopCarousel(element);
    }
    else {
        startCarousel(element);
    }
    flag = !flag;
}

【讨论】:

  • 旁注:toggleCarousel 需要更新以将源元素传递给stopCarouselstartCarousel
  • 确实如此,但toggleElement 调用startCarousel(event)startElement 期望参数是一个元素,而不是一个事件(据我所知)。
  • 好电话;可以添加到答案中。
  • 谢谢!我实际上不必通过目标,因为我可以设置它。此外,我想取消注释 mouseover 并离开,以便我可以同时使用两者,并且在事件中设置函数也有助于实现这一点。我对 this 引用事件对象感到困惑,我可以立即引用它。新鲜空气即将到来!
【解决方案2】:

您的.click() 事件绑定未绑定要在单击.figure 时调用的函数。它使用当时有效的this 对象(window)直接调用toggleCarousel。您需要向.click()提供回调函数。

将:$('.figure').click(toggleCarousel(this)); 更改为:

$('.figure').click(function(){
    toggleCarousel(this);
});

以便在单击时使用正确的this 对象调用toggleCarousel。正如您的代码现在一样,它不符合 JQuery signature for .click() 并尝试使用在第一次遇到代码时处于控制状态的 this 对象立即调用 toggleCarousel,这是window


this 对象绑定在 JavaScript 中是可变的……也就是说,它并不总是指向同一个对象,并且它的绑定可以从一行代码更改为下一行。 如何调用包含单词this 的代码决定了它将绑定到哪个对象。

您可以按照以下清单了解this 将绑定的内容 到...

如果包含this的代码被调用:

  1. 作为对象实例的方法或属性(通过实例变量):

    var o = new Object(); 
    
    // "this" will be bound to the "o" object instance
    // while "someProperty" and "someMethod" code executes
    o.someProperty = someValue;
    o.someMethod();
    
  2. 通过.call().apply().bind()Array.prototype.fn 调用:

    // "this" will be bound to the object suppled as the "thisObjectBinding"
    someFunction.call(thisObjectBinding, arg, arg);
    someFunction.apply(thisObjectBinding, [arg, arg]);
    var newFunc = someFunction.bind(thisObjectBinding, arg, arg);
    

    注意:当调用回调函数(即事件处理程序)时,事件触发时会隐式调用该处理程序。在这些情况下,负责触发事件的对象成为绑定到this 的对象。

    此外,几个Array.prototype 方法允许传递thisObject,这将在方法调用期间改变绑定:

    Array.prototype.every( callbackfn [ , thisArg ] )
    Array.prototype.some( callbackfn [ , thisArg ] )
    Array.prototype.forEach( callbackfn [ , thisArg ] )
    Array.prototype.map( callbackfn [ , thisArg ] )
    Array.prototype.filter( callbackfn [ , thisArg ] )
    
  3. 如果其他情况均不适用,则发生默认绑定。

    3a。 "use strict" 生效:thisundefined

    3b。没有"use strict" 生效:this 绑定到全局对象

注意事项:

a) this 绑定也可以通过使用 eval() 来影响,但作为 一般最佳实践,应避免使用eval()

b) 当 HTML 属性用于将 DOM 元素连接到事件时 处理程序(即onclickonload 等)、匿名全局包装器 函数是围绕事件处理属性的值创建的, 从而使全局对象 (window) 成为 this 对象。这是 避免内联 HTML 事件属性的几个原因之一。

【讨论】:

  • 既然你已经给出了这个答案,为什么不直接标记为重复...*.com/questions/41091653/…
  • @ScottMarcus:不,不是。作为一个社区,我们从问题本身中询问了很多细节。我们作为一个社区也应该具体回答。你的回答很笼统。
  • @NewToJS 因为每次我尝试这样做时,SO 社区都会回应说当前的问题与那个不同!
  • @SaniSinghHuttunen 我的回答给出了一组特定的this 绑定规则。
  • 然后发表评论? “也许这个答案会帮助你Link to relevant answer
【解决方案3】:

这可能不是最好或最直接的答案,但希望这能帮助您了解您错过了什么。

在 javaScript 中,this 对象是在函数调用期间设置的,实际上。 (尽管请注意此处的扩展答案,详细说明了this 的定义/绑定方式)。考虑一下:

function this_test () { console.log( this ); }

this_test(); // prints nothing

var x = {f:this_test}; // note, references to functions are not the same as function calls
x.f(); // prints {f:[function]} ie this==x inside the call

this_test.call( x ); // identical in effect to above.

考虑到这一点,考虑一下你写的这行:

$('.figure').click(toggleCarousel(this));

它的作用是设置一个事件处理函数,它是调用toggleCarousel(this) 的结果。因为(我假设)这是 js 文件或脚本标记中的*代码,在此上下文中 this === window 因为它不在函数内!

你应该做的是:

$('.figure').click( toggleCarousel );

最后,由于您使用的是 jQuery,您应该使用 jQuery 方法来查找和修改 DOM,因为它更容易(并且兼容跨浏览器)。因此这个习语有时会出现在 jQuery 事件代码中:

function event_handler () {
    var $this = $(this);
}

强烈建议阅读 - jQuery Click Event - 大多数其他事件处理程序的工作方式类似。

【讨论】:

    最近更新 更多