问题
Short story, I don\'t know why it\'s not working, I\'ve tried Console.Log() to figure out what \'this\' is and the event just keeps passing window. It\'s a click event that\'s suppose to activate effects on a certain figure in this carousel, which is why I can\'t just individually search for class (at least to my knowledge). Any fix from the smarter?
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>
回答1:
You aren't attaching the event handler correctly. This line:
$('.figure').click(toggleCarousel(this));
...is calling toggleCarousel
with this
immediately (that's what the parens will do). What you really want is to pass the function object to .click()
:
$('.figure').click(toggleCarousel);
Update:
As @FelixKling pointed out, you'll also want to pass the target of the event to the downstream functions; it looks like they expect an element, not the event. Also, bool
will be reset to false
each call, which is not what you want; you should put it in the closure:
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;
}
回答2:
Your .click()
event binding isn't binding a function to be called when .figure
gets clicked. It's making a direct call to toggleCarousel
using the this
object in effect at the time (window
). You need to provide a callback function to .click()
.
Change: $('.figure').click(toggleCarousel(this));
to:
$('.figure').click(function(){
toggleCarousel(this);
});
So that toggleCarousel
is invoked using the correct this
object at the time of the click. As your code is now, it doesn't conform to the JQuery signature for .click() and attempts to invoke toggleCarousel
immediately using the this
object which is in control at the time the code is first encountered, which is window
.
The this
object binding is volatile in JavaScript...that is, it doesn't always point to the same object and its binding can change from one line of code to the very next. How you invoke the code that contains the word this
determines what object it will bind to.
Here's a checklist that you can follow to know what
this
will bind to...
If the code that contains this
is invoked:
As a method or property of an object instance (through an instance variable):
var o = new Object(); // "this" will be bound to the "o" object instance // while "someProperty" and "someMethod" code executes o.someProperty = someValue; o.someMethod();
Via a
.call()
,.apply()
,.bind()
orArray.prototype.fn
invocation:// "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);
Note: When a callback function is invoked (i.e. event handler), there is an implicit call to the handler when the event is triggered. In these cases, the object responsible for triggering the event becomes the object bound to
this
.Additionally, several
Array.prototype
methods allow for athisObject
to be passed which will alter the binding for the duration of the method call: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 ] )
If none of the other scenarios apply, Default binding occurs.
3a. With
"use strict"
in effect:this
isundefined
3b. Without
"use strict"
in effect:this
binds to the Global object
NOTES:
a)
this
binding can also be affected by usingeval()
, but as a general best practice, the use ofeval()
should be avoided.b) When HTML attributes are used to wire DOM elements to event handlers (i.e.
onclick
,onload
, etc.), anonymous global wrapper functions are created around the value of the event handling property, thus making the Global object (window
) thethis
object. This is one of several reasons to avoid inline HTML event attributes.
回答3:
This may not be the best or most direct answer but hopefully this will help you to understand what you've missed.
In javaScript the this
object is set during a function call, in effect. (although do take note of the extended answer here detailing how this
is defined / bound). Consider 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.
With that in mind, consider this line you wrote:
$('.figure').click(toggleCarousel(this));
What this does is set an event handler function that is the result of calling toggleCarousel(this)
. Because this is (I assume) top-level code in a js file or in a script tag, in this context this === window
because it's not inside a function!
What you should be doing is this:
$('.figure').click( toggleCarousel );
Finally, since you're using jQuery, you ought to use jQuery methods to lookup and modify DOM since it's far easier (and cross-browser compliant). Hence this idiom sometimes seen in jQuery event code:
function event_handler () {
var $this = $(this);
}
Highly suggested reading - jQuery Click Event - most other event handlers work similarly.
来源:https://stackoverflow.com/questions/41496958/this-does-not-work-properly-in-another-event-im-clueless-as-to-why