简体   繁体   中英

Javascript prototype property returning undefined in function

Creating image rotator using prototypal inheritance, I keep getting an error in the console displaying: TypeError: this.curPhoto is undefined this.curPhoto.removeClass('previous'); I put this in the callback function of one of the functions used to switch the positions of the overlapping divs (stack under each other) Here is the code:

    <script src='https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js'></script>
    <script src='ImageRotatorOOP.js' type='text/javascript'> </script>
    <script type='text/javascript'>
    $('document').ready(function() {
    setInterval('rotateImages()', 2000);
    });

    function rotateImages() {
    var imageRotator = new ImageRotator($('#photoShow'));
    if(imageRotator.nextPhoto.length == 0) {
        imageRotator.nextPhoto = imageRotator.container.children().first();
    }

    imageRotator.stackImages();
    }
    </script>

    </head>
  <body>
  <h1> Image Rotator </h1>
  <div id='photoShow'>
<div class='current'>
    <img src='images/RoyMustang.jpg' alt='Roy Mustang' />
</div>
<div>
    <img src='images/nhk.png' alt='Welcome to the NHK' />
</div>
<div>
    <img src='images/dragonball_z.jpg' alt='Dragonball Z'/>
</div>
</div>
</body>
</html>

And The .js file

    var ImageRotator = function(container) {
this.container = container;
this.curPhoto = this.container.find('div.current');
this.nextPhoto = this.curPhoto.next('div'); 
}

ImageRotator.prototype.stackImages = function() {
    this.curPhoto.removeClass('current').addClass('previous');
    this.nextPhoto.css({opacity: 0.0}).addClass('current').animate({opacity: 1.0}, 1000,      function() {
        this.curPhoto.removeClass('previous');
    });
}

Here is the css file

   #photoShow img {
    width: 400px;
    height: 300px;  
    }

    #photoShow div {
    position: absolute;
    z-index: 0;
    }

    #photoShow div.previous {
    z-index: 1;
    }

    #photoShow div.current {
    z-index: 2;
    }

In the animation completion function, the value of this will be the DOM object animating, not your ImageRotator object. You can fix that issue by doing something like this:

ImageRotator.prototype.stackImages = function() {
    this.curPhoto.removeClass('current').addClass('previous');
    var self = this;
    this.nextPhoto.css({opacity: 0.0}).addClass('current').animate({opacity: 1.0}, 1000, function() {
        self.curPhoto.removeClass('previous');
    });
}

Note: this is a common issue with callback functions because every function call in Javascript sets a new value for this so unless the animation callback is specifically designed to set the value of this to what you want, it will be set to something else. Saving the value into a local variable before the embedded callback is a common work-around. You could also use .bind() which does something similar, but does it for you.

Here's an example using .bind() :

ImageRotator.prototype.stackImages = function() {
    this.curPhoto.removeClass('current').addClass('previous');
    this.nextPhoto.css({opacity: 0.0}).addClass('current').animate({opacity: 1.0}, 1000, function() {
        this.curPhoto.removeClass('previous');
    }.bind(this));
}

The issue is in this section of code:

ImageRotator.prototype.stackImages = function() {
    this.curPhoto.removeClass('current').addClass('previous');
    this.nextPhoto.css({opacity: 0.0}).addClass('current').animate({opacity: 1.0}, 1000,      function() {
        this.curPhoto.removeClass('previous');
    });
}

On the line, this.curPhoto.removeClass('previous'); , this does not refer to the ImageRotator instance but to a jQuery object.

You can fix this by saving the value of this in the closure above.

ImageRotator.prototype.stackImages = function() {
    var that = this;
    this.curPhoto.removeClass('current').addClass('previous');
    this.nextPhoto.css({opacity: 0.0}).addClass('current').animate({opacity: 1.0}, 1000,      function() {
        that.curPhoto.removeClass('previous');
    });
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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