调用函数遇.call()未定义报错?滚动图片切换问题求助
修复滚动触发图片切换时的"Cannot read properties of undefined (reading 'call')"错误
错误原因分析
出现该错误的核心原因有两个:
- 从
data-step属性获取到的步骤编号是字符串类型(比如'0'),而数组steps使用数字索引,直接用字符串索引无法匹配到对应的函数,导致steps[step]为undefined,调用.call()时触发报错。 createGraphic函数未返回包含update方法的对象,外部无法正常调用graphic.update(step)。
修复步骤
1. 转换步骤编号为数字类型
在触发步骤切换的回调中,将字符串类型的step转为数字:
var handleItemFocus = function(event, item) { // 把字符串转为十进制数字 var step = parseInt(item.data.step, 10); graphic.update(step); }
或者在update函数内部做类型转换,同时增加存在性判断避免报错:
function update(step) { step = parseInt(step, 10); console.log(step); // 先判断对应步骤函数是否存在,再调用 if (steps[step]) { steps[step].call(); } }
2. 暴露update方法给外部调用
修改createGraphic函数,在末尾返回包含update方法的对象,确保外部能正常调用:
window.createGraphic = function(graphicSelector) { var graphicEl = d3.select('.graphic') var graphicVisEl = graphicEl.select('.graphic__vis') var graphicProseEl = graphicEl.select('.graphic__prose') var dv = document.getElementById('image') var img = document.createElement("IMG") // actions to take on each step of our scroll-driven story var steps = [ function step0() { while (dv.hasChildNodes()) { dv.removeChild(dv.lastChild); } img.src = "./img/spec_fic_pg_1.png"; img.width = "100%"; img.height = "auto"; dv.appendChild(img); }, function step1() { while (dv.hasChildNodes()) { dv.removeChild(dv.lastChild); } img.src = "./img/spec_fic-02.png"; img.width = "100%"; img.height = "auto"; dv.appendChild(img); }, ] // update our img function update(step) { step = parseInt(step, 10); console.log(step); if (steps[step]) { steps[step].call(); } } // 返回包含update方法的对象 return { update: update }; }
3. 优化图片切换逻辑(可选)
原代码每次切换都删除DOM节点再重新添加,可简化为直接修改已有图片的src属性,减少DOM操作开销:
window.createGraphic = function(graphicSelector) { var dv = document.getElementById('image'); // 提前创建图片元素并添加到容器 var img = document.createElement("IMG"); img.width = "100%"; img.height = "auto"; dv.appendChild(img); var steps = [ function step0() { img.src = "./img/spec_fic_pg_1.png"; }, function step1() { img.src = "./img/spec_fic-02.png"; }, ]; function update(step) { step = parseInt(step, 10); if (steps[step]) { // 无特殊上下文需求时,直接调用函数即可,无需使用call() steps[step](); } } return { update: update }; }
内容的提问来源于stack exchange,提问作者user24690595
相关产品推荐
相关产品推荐

