在for循环的jQuery hover函数中输出JavaScript数组值出现undefined问题
问题原因与解决方法
嗨,这个问题是JavaScript新手很容易碰到的闭包陷阱,我来给你拆解一下:
为什么会出现undefined?
你代码里的循环变量x没有用let/var/const声明,默认变成了全局变量。而且循环是同步执行的,当循环结束后,x的值已经变成了5(因为segmentTitle的长度是5,循环条件x < 5不满足时退出,此时x=5)。
而hover的回调函数是异步触发的——只有当鼠标真的悬停到元素上时才会执行。这时候再去取x的值,它已经是5了,可你的数组索引最大是4,segmentTitle[5]和segmentParagraph[5]自然就是undefined啦。
几种解决方法
方法1:用let声明循环变量(最简洁)
let有块级作用域,每次循环都会创建一个独立的x变量,每个hover回调绑定的都是当前循环的x值:
jQuery(document).ready(function($){ var originalWheelContent = $('.wheel-content').html(), transitionSpeed = 400, segmentTitle = ['collaborative','compassionate','inclusive','empowering','responsive'], segmentParagraph = [ 'Working together to deliver the best possible outcomes and recognises and values the contribution of others.', 'Constantly looking for new ways to satisfy the needs of those you work with or care for. Acting with consideration and understanding for others feelings.', 'Actively seeking and creating opportunities to include others, fostering an environment where everyone feels valued and respected.', 'Enabling positive change and supporting others to reach their maximum potential.', 'Reacting positively to change and others needs by being creative and innovative in finding solutions.' ]; // 这里把x改成let声明 for(let x = 0; x < segmentTitle.length; x++){ $('.wheel-graphic map area#' + segmentTitle[x]).hover( function(){ $('.wheel-content').fadeOut(transitionSpeed,function(){ $('.wheel-content').replaceWith('<div class="wheel-content"><h2 class="segment-title">' + segmentTitle[x] + '</h2><h4 class="segment-p">' + segmentParagraph[x] + '</h4></div>'); }); }, function() { $('.wheel-content').fadeIn(transitionSpeed); $('.wheel-content').replaceWith('<div class="wheel-content">' + originalWheelContent + '</div>'); } ); } });
方法2:用立即执行函数(IIFE)保存变量
通过立即执行函数把当前循环的x值封装成独立的作用域,避免后续修改影响回调:
jQuery(document).ready(function($){ var originalWheelContent = $('.wheel-content').html(), transitionSpeed = 400, segmentTitle = ['collaborative','compassionate','inclusive','empowering','responsive'], segmentParagraph = [ 'Working together to deliver the best possible outcomes and recognises and values the contribution of others.', 'Constantly looking for new ways to satisfy the needs of those you work with or care for. Acting with consideration and understanding for others feelings.', 'Actively seeking and creating opportunities to include others, fostering an environment where everyone feels valued and respected.', 'Enabling positive change and supporting others to reach their maximum potential.', 'Reacting positively to change and others needs by being creative and innovative in finding solutions.' ]; for(var x = 0; x < segmentTitle.length; x++){ // 用立即执行函数保存当前index (function(index){ $('.wheel-graphic map area#' + segmentTitle[index]).hover( function(){ $('.wheel-content').fadeOut(transitionSpeed,function(){ $('.wheel-content').replaceWith('<div class="wheel-content"><h2 class="segment-title">' + segmentTitle[index] + '</h2><h4 class="segment-p">' + segmentParagraph[index] + '</h4></div>'); }); }, function() { $('.wheel-content').fadeIn(transitionSpeed); $('.wheel-content').replaceWith('<div class="wheel-content">' + originalWheelContent + '</div>'); } ); })(x); } });
方法3:用forEach遍历数组(更直观)
数组的forEach方法会给每个元素绑定独立的回调,参数里的index就是当前元素的索引,天然避开闭包问题:
jQuery(document).ready(function($){ var originalWheelContent = $('.wheel-content').html(), transitionSpeed = 400, segmentTitle = ['collaborative','compassionate','inclusive','empowering','responsive'], segmentParagraph = [ 'Working together to deliver the best possible outcomes and recognises and values the contribution of others.', 'Constantly looking for new ways to satisfy the needs of those you work with or care for. Acting with consideration and understanding for others feelings.', 'Actively seeking and creating opportunities to include others, fostering an environment where everyone feels valued and respected.', 'Enabling positive change and supporting others to reach their maximum potential.', 'Reacting positively to change and others needs by being creative and innovative in finding solutions.' ]; // 用forEach遍历,直接拿到title和index segmentTitle.forEach(function(title, index){ $('.wheel-graphic map area#' + title).hover( function(){ $('.wheel-content').fadeOut(transitionSpeed,function(){ $('.wheel-content').replaceWith('<div class="wheel-content"><h2 class="segment-title">' + title + '</h2><h4 class="segment-p">' + segmentParagraph[index] + '</h4></div>'); }); }, function() { $('.wheel-content').fadeIn(transitionSpeed); $('.wheel-content').replaceWith('<div class="wheel-content">' + originalWheelContent + '</div>'); } ); }); });
小提示
以后写代码记得不要省略变量声明,像你原来代码里的x没加let/var,会变成全局变量,很容易引发其他奇怪的问题哦~
内容的提问来源于stack exchange,提问作者Paul Bamforth
相关产品推荐
相关产品推荐

