'this' 在另一个事件中不能正常工作。我不知道为什么

IT技术 javascript jquery events this
2021-02-09 22:09:46

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

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>

3个回答

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

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

...被调用 toggleCarouselthis立即(这是什么括号都行)。真正想要的是将函数对象传递.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;
}
它确实如此,但toggleElement调用startCarousel(event)startElement期望参数是一个元素,而不是一个事件(据我所知)。
2021-03-13 22:09:46
好决定; 可以补充回答。
2021-03-13 22:09:46
谢谢!我实际上不必通过目标,因为我可以直接设置它。此外,我想取消对鼠标悬停的评论并离开,以便我可以同时使用两者,并且在事件中设置函数也有助于实现这一点。我一直困惑于 this 引用了事件对象,我可以立即引用它。新鲜空气即将来临!
2021-03-17 22:09:46
旁注:toggleCarousel需要更新以将源元素传递给stopCarouselstartCarousel
2021-03-25 22:09:46

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

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

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

因此在单击时toggleCarousel使用正确的this对象调用它就像您现在的代码一样,它不符合JQuery 签名,.click()并尝试toggleCarousel使用在this第一次遇到代码时处于控制状态对象立即调用,即window.


thisJavaScript 中对象绑定是可变的……也就是说,它并不总是指向同一个对象,并且它的绑定可以从一行代码更改为下一行。您如何调用包含该词的代码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传递a ,这将在方法调用期间改变绑定:

    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等)时,会围绕事件处理属性的值创建匿名全局包装函数,从而使 Global 对象 ( window) 成为this对象。这是避免内联 HTML 事件属性的几个原因之一。

@ScottMarcus:不,不是。作为一个社区,我们从问题本身中询问了很多细节。我们作为一个社区也应该具体回答。你的回答很笼统。
2021-03-14 22:09:46
然后发表评论?“也许这个答案对你有帮助Link to relevant answer
2021-03-21 22:09:46
为什么不只是标记为重复,因为你已经给出了这个答案... stackoverflow.com/questions/41091653/ ...
2021-04-01 22:09:46
@NewToJS 因为每次我尝试这样做时,SO 社区都会回应说当前的问题与那个问题不同!
2021-04-11 22:09:46
@SaniSinghHuttunen 我的回答为如何this 绑定提供了一组特定的规则
2021-04-11 22:09:46

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

在 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 - 大多数其他事件处理程序的工作方式类似。