【问题标题】:Alternative way to using eval( ) to creating a dynamic variable within a for( ) while running jQuery?在运行 jQuery 时使用 eval() 在 for() 中创建动态变量的替代方法?
【发布时间】:2023-12-19 22:50:02
【问题描述】:

我是 JS 的新手,对 jQuery 不是很熟悉,但我想尝试一下动态调用 slimbox's multi-image function

例如,在我的网站上有一个照片滑块随机循环显示 3 张图像,我希望 slimbox 为第一张显示另外 2 张图像,在最后一张显示另外 1 张图像。这意味着 slimbox 将在幻灯片中显示总共 6 张图像。

因此,如果您需要,下面是详细的演练:当用户访问我的网站时,用户将看到一个 div 块,该块一次显示 1 张图像。照片滑块中的图像将旋转到下一个(随机加载的 3 个)。当用户点击图片时,用户将触发 slimbox(轻量级灯箱),更大的幻灯片将占据屏幕(使背景变暗)。通过 slimbox,用户将看到最多 6 张图片循环。

为了创建动态变量,我尝试在 FOR 循环中使用 EVAL,但在运行 jQuery 时失败。不过,EVAL 在循环之外工作。我不确定要使用哪个其他功能。让我们深入研究代码...

通过 JS 调用 slimbox:

// usage as shown for multi-image slideshow.  yes, there are arrays within an array
jQuery.slimbox([["image","desc"], ["image","desc"], ["image","desc"]], startAtImage);

// or simplified further
jQuery.slimbox([[array1], [array3], [array2]], startAtImage);

// after appending the images to select the first and last images 
jQuery.slimbox([[array1], [array4], [array5], [array3], [array2], [array6]], startAtImage);

这是我动态调用 slimbox 函数的尝试:

var imgAlbum = "summer";

var arrayGiven = [1,3,2];       // randomized image order given

var img1 = [4,5];               // registering images to be appended -- aiming for [1,4,5]
var img2 = [6];                 // registering images to be appended -- aiming for [2,6]

var desc1 = "Description #1";   // unique descriptions
var desc2 = "Description #2";
var desc3 = "Description #3";
var desc4 = "Description #4";
var desc5 = "Description #5";
var desc6 = "Description #6";

var arrayExtended = arrayGiven;

for(var i=1; i<=3; i++){                                            // cycle through arrayGiven and append images
    var imgLocate = i;
    var imgAtIndex = jQuery.inArray(imgLocate,arrayExtended);       // locating array index number of a specific image.  if imgLocate = 1, then imgAtIndex = 0 , if 2 then 4, and so forth
    var imgAfter = imgAtIndex + 1;                                  // allows appending to selected image at index

    eval("var imgCurrent = img" + imgLocate + ";");                 // creating dynamic variable
    if(imgCurrent != null){
        arrayExtended.splice(imgAfter, 0, imgCurrent); 
    }       
}   // alert(arrayExtended) should be [1,4,5,3,2,6]

for(var i=1; i<=arrayExtended.length; i++){
    var imgLocate = i;

    eval("var array" + imgLocate + " = ['img/" + imgAlbum +  "/" + imgLocate + ".jpg',desc" + imgLocate + "];");    // if imgLocate = 1, then var array1 = ['img/summer/1.jpg',desc1];
                                                                                                                    // array1 array2 array3 array4 array5 array 6 ... now defined
}

var arrayMain = [];

for(var i=1; i<=arrayExtended.length; i++){                         // must wait for arrays to be built before adding to arrayMain
    var atIndex = i - 1;

    var imgAtIndex = jQuery.inArray(imgLocate,arrayExtended);       // if imgLocate = 1, then imgAtIndex = 0 , if 2 then 4

    eval("arrayMain.push('[' + array" + arrayExtended[atIndex] + " + ']');");
}

var imgClicked = 0;                                                 // clicked on image within arrayExtended index 0
var startAtImage = imgClicked;                                      // slimbox slideshow will start on 1.jpg

jQuery.slimbox("[" + mainArray + "]",startAtImage);

最后希望得到以下结果:

jQuery.slimbox([["img/summer/1.jpg","Desciption #1"], ["img/summer/4.jpg","Desciption #4"], ["img/summer/5.jpg","Desciption #5"], ["img/summer/3.jpg","Desciption #3"], ["img/summer/2.jpg","Desciption #2"]], ["img/summer/6.jpg","Desciption #6"], 0);

任何帮助或建议将不胜感激!有很多东西要学。

于 11 年 8 月 26 日更新 根据建议改变结构。还将更多图像和组添加到数组中,以更好地说明所需的功能。尝试从 img 对象调用图像组(1、2、7)时出现错误:

        var imgAlbum = "summer";

        var arrayGiven = [1,3,2,7,11];      // randomized image order given

        var img = {
          1: [4,5],
          2: [6],
          7: [10,8,9]
        };

        var desc = {
          1: 'Description #1',
          2: 'Description #2',
          3: 'Description #3',
          4: 'Description #4',
          5: 'Description #5',
          6: 'Description #6',
          7: 'Description #7',
          8: 'Description #8',
          9: 'Description #9',
          10:'Description #10',
          11:'Description #11'
        };

        var arrayExtended = arrayGiven.slice();

        for(var i=1; i<=arrayGiven.length; i++){                                        
            var imgLocate = i;
            var imgAtIndex = jQuery.inArray(imgLocate,arrayExtended);       
            var imgAfter = imgAtIndex + 1;                                  
            var imgCurrent = img[imgAfter];

            if(imgCurrent != null){
                arrayExtended.splice(imgAfter, 0, imgCurrent); 
            }       
            //alert(imgCurrent);    // shows 4,5 undefined undefined undefined undefined
        }   //alert(arrayExtended);// shows 1,4,5,3,2,6,7,10,8,9,11
        var imgArray = {};
        for(var i=1; i<=arrayExtended.length; i++){
            var imgLocate = i;
            var atIndex = i - 1;

            imgArray[imgLocate] = ['imgs/'+imgAlbum+'/'+imgLocate+'.jpg', desc[imgLocate]];
        }

        var mainArray = [];

        for(var i=1; i<=arrayExtended.length; i++){                         
            var imgLocate = i;                  
            var atIndex = i - 1;

            mainArray.push(imgArray[arrayExtended[atIndex]]);   
            //alert(imgArray[arrayExtended[atIndex]]); // shows (simplified) 1.jpg,Desc#1 undefined 3.jpg,Desc#3 2.jpg,Desc#2 undefined undefined

        }

        var imgClicked = 0;                                                 
        var startAtImage = imgClicked; 

jQuery.slimbox(mainArray,startAtImage);

更新了 2011 年 8 月 30 日的最终解决方案 应用了修复并从生产代码中添加了随机化器。结果是准确的。如果您打算使用随机化器,我建议将要附加的图像保持在 getRandomArray 范围之外,除非您希望看到重复项。

感谢大家的大力支持!

function getRandomArray(min,max){
            var A= [];
            while(max>= min) A.push(max--)    
            A.sort(function(){return .5- Math.random()});  
            return A;
        }
        var randomness = getRandomArray(1,11).slice();
        var leadingZeroArray = randomness.slice();
        leadingZeroArray.unshift("0");          // was needed for my project, but if removed, everything else will need to be re-adjusted

        var arrayGiven = randomness.slice();    // or you can plug in -> var arrayGiven = [1,3,2,7,11]; for original example

        var imgAlbum = "summer";
        var img = {
          1: [4,5],
          2: [6],
          7: [10,8,9]
        };
        var desc = {
          1: 'Description #1',
          2: 'Description #2',
          3: 'Description #3',
          4: 'Description #4',
          5: 'Description #5',
          6: 'Description #6',
          7: 'Description #7',
          8: 'Description #8',
          9: 'Description #9',
          10:'Description #10',
          11:'Description #11'
        };

        var arrayExtended = arrayGiven.slice();

        for(var i=0; i<arrayGiven.length; i++){                                         
            var imgLocate = arrayGiven[i]; 
            var imgAtIndex = jQuery.inArray(imgLocate,arrayExtended);       
            var imgAfter = imgAtIndex + 1;                                  
            var imgCurrent = img[imgLocate];

            if(imgCurrent != null){
                if(imgCurrent.length > 0){
                    for(var j=imgCurrent.length-1; j>-1; j--){
                        var imgMore = imgCurrent[j];
                        arrayExtended.splice(imgAfter, 0, imgMore); 
                    }
                }
                else{arrayExtended.splice(imgAfter, 0, imgCurrent); }
            }
        }   
        var imgArray = {};
        for(var i=1; i<=arrayExtended.length; i++){
            var imgLocate = i;
            var atIndex = i - 1;

            imgArray[imgLocate] = ['images/'+imgAlbum+'/'+imgLocate+'.jpg', desc[imgLocate]];
        }
        var mainArray = [];
        for(var i=1; i<=arrayExtended.length; i++){                         
            var imgLocate = i;                  
            var atIndex = i - 1;

            mainArray.push(imgArray[arrayExtended[atIndex]]);   
        }

        var imgClickedOn = 5;
        var imgAtIndex = jQuery.inArray(imgClickedOn,arrayExtended);

        jQuery.slimbox(mainArray,imgAtIndex);

【问题讨论】:

  • 我认为可能有更简单的方法可以做到这一点,但我在理解代码的 intent 时遇到了一些麻烦。你认为你可以稍微编辑一下这个问题来描述你想要代码做什么,最后?
  • 我在第二段下方添加了更多信息。
  • 我实际上在想你的代码,第二段。你的意思是你想将总共六张图片传递给 Slimbox,第一张、第四张和第五张是随机的,但想要两张特定的图片作为第二张和第三张,另一张放在最后?或者,您的意思是要以随机顺序显示三张图像,两张图像在一个特定的图像之后(图像#1),另一个在不同的特定图像之后(图像#2),无论它们在随机排列中的哪个位置?或者,你还有别的意思吗?
  • 回答有点晚了,但不妨......页面将随机显示 3 张随机图像。当用户单击图像并且该特定图像具有与其链接的其他图像时,slimbox 将显示单击的特定图像以及要跟随的 X 链接图像。图片链接 (1.jpg -> 4.jpg, 5.jpg) (2.jpg -> 6.jpg) 将被添加到数组中。所以如果在主页上,我们在photoslider中看到这样的图像顺序:3.jpg,1.jpg,2.jpg,当点击2.jpg时,slimbox会显示2.jpg,6.jpg,1.jpg, 4.jpg、5.jpg、3.jpg。这样就清楚了吗?

标签: javascript jquery arrays eval slimbox


【解决方案1】:

不要为img 使用多个变量,而是使用数组或对象。

var img = {
  1: [4,5],
  2: [6]
};

那么你可以代替eval("var imgCurrent = img" + imgLocate + ";");

var imgCurrent = img[imgLocate];

你可以为:

eval("var array" + imgLocate + " = ['img/" + imgAlbum +  "/" + imgLocate + ".jpg',desc" + imgLocate + "];");

创建一个对象并将数组放入其中:

var desc = {
  1: 'Description #1',
  2: 'Description #2',
  3: 'Description #3',
  4: 'Description #4',
  5: 'Description #5',
  6: 'Description #6'
};
var imgArray = {};
imgArray[imglocate] = ['img/'+imgAlbum+'/'+imgLocate+'.jpg', desc[imgLocate]];

编辑:尝试将for(var i=1; i&lt;=arrayGiven.length; i++){ 中的var imgLocate = i; 更改为var imgLocate = arrayGiven[i];

【讨论】:

  • 嘿火箭,这是迄今为止最好的解决方案。虽然,我遇到了墙壁,就像从对象传递数组值一样。下面是代码现在的样子:jQuery.slimbox(mainArray,startAtImage);
  • 更正虽然,我遇到了墙壁,就像从对象传递数组值一样。以下是在应用您的修复和 Sidncious 的括号修复之后代码现在的样子:mainArray.push(imgArray[arrayExtended[atIndex]]); //alert(imgArray[arrayExtended[atIndex]]); shows (simplified) 1.jpg,Desc#1 undefined 3.jpg,Desc#3 2.jpg,Desc#2 undefined jQuery.slimbox(mainArray,startAtImage); 4,5 是一个,6 是另一个,但它们与 1,3,2 的值不同。如果您愿意,我可以更新我的原始帖子以展示我的全部作品。
  • @Transattic:你能更新原帖吗?这也让其他人更容易提供帮助。
  • 感谢您的解决方案。经过更多的调试,现在一切正常。已发布更新。
【解决方案2】:

全局变量是window对象的成员,所以你可以这样做:

var imgCurrent = window["img" + imgLocate];

但是,使用这样的动态变量名称并不是一个好习惯。你应该把值放在一个数组中:

var img = [
  [4,5],
  [6]
];

现在您可以访问数组项:

var imgCurrent = img[imgLocate];

但请注意,数组索引从 0 开始,而不是 1。

【讨论】:

  • 谢谢。不过,对象方法有助于更好地组织“数组”。
【解决方案3】:

一些快速说明:

  1. 请不要使用eval()。在极少数情况下需要它,而且它会影响性能和安全性。

  2. 您发现 JavaScript 没有“变量变量”(通过名称获取或设置变量的能力),这就是您不得不求助于 eval() 的原因。当你需要从一组中查找某些东西时,不要使用一堆编号的变量。尝试使用数组或对象。

  3. 当您将 JavaScript 中的对象分配给变量时,它们不会被复制。线

    var arrayExtended = arrayGiven;
    

    不复制arrayGivenarrayExtended 最终成为指向同一数组的变量。因此,当您在arrayExtended 中更改某些内容时,它也会在arrayGiven 中更改它。如果您需要在 JavaScript 中复制数组,请使用不带参数的 .slice()

    var arrayExtended = arrayGiven.slice();
    

    JavaScript 中的其他一些东西,比如对象,更难复制。

  4. 你想在这里做什么? (mainArray 已经是一个数组)这将创建一个字符串,它是一个“[”,然后是 mainArray 的字符串表示形式(数组中的每个项目用逗号分隔),然后是“]”。 Slimbox 不知道如何处理它。

    jQuery.slimbox("[" + mainArray + "]",startAtImage);
    

    如果您确实想将某些东西包装在一个数组中,只需像上面那样在它周围加上括号:

    [mainArray];
    

我认为您的主要问题是"[" + mainArray + "]"。有了这些技巧,您应该能够使您的代码工作(并且,没有eval())。但是,我也想向您展示我解决这个问题的方法。在下面。

我将所有图像的名称和描述存储在一个数组中。因为 JavaScript(以及许多其他编程语言)中的数组从 0 而不是 1 开始,所以我从指定顺序的数组中的所有图像编号中减去 1。

var album = "summer",
    images = [
        [
            { name: "1", description: "Description #1" },
            { name: "4", description: "Description #4" },
            { name: "5", description: "Description #5" }
        ],
        [
            { name: "2", description: "Description #2" },
            { name: "6", description: "Description #6" }
        ],
        [
            { name: "3", description: "Description #3" }
        ]
    ],
    order = [0, 2, 1],
    startAtImage = 0,
    slimboxImages = Array.prototype.concat.apply([], order.map(function(id){ return images[id]; }))
        .map(function(image){
            return [ 'img/' + album + '/' + image.name + '.jpg', image.description];
        });

jQuery.slimbox(slimboxImages, startAtImage);

【讨论】:

  • 1. to 3. 很高兴知道这些事情,谢谢。 4. 如果我在数组中间添加一个值(不更改值),该方法会代替拼接吗? 5. 我注意到我的代码不起作用,因为括号是字符串。这有助于修复输入,感谢您的洞察力。当我回来时,我将阅读您的其余代码。
  • 嘿 Sidncious,我刚刚运行了您提出的版本,发现它在处理随机订单时存在问题。是的,它适用于订单 [0,2,1](或 imgs 1,3,2 以避免与原始问题混淆),但是当输入订单 [2,1,0](imgs 3,2,1)时, slimbox 按以下顺序显示:3、4、5、2、1、6。我们应该期待这个结果:3,2,6,1,4,5。关于如何更好地接受随机订单有什么想法吗?
  • @Transattic 我误解了你想要做什么。本质上,您希望将一些图像组合在一起。一些图像是随机的,但其他图像总是出现在特定图像之后。我编辑了我的答案,看看。
  • 这适用于这 3 个图像组。我想我没有提到这应该适用于多达 50 个或更多的大量图像。所以会有很多点,点击的图像不会是该特定组中的第一个。我只是通过添加组来运行测试,如下所示:图像数组索引 #0 (1,4,5) #1 (2,6) #2 (3) #3 (7,10,8,9) #4 (11 )。当用户单击 (startAtImage) 索引 #10 (img 11) 时,slimbox 会显示 img 9。如果单击索引 #6 (img 7),则会显示 img 11。我不确定这是如何工作的,但它会是可以总是从点击的 img 开始吗?
  • @Transattic 我猜startAtImage 没有考虑额外的图像(图像可能位于order 数组中的一个位置,但就 Slimbox 而言位于另一个位置担心,如果额外的(分组的)图像出现在它之前。
【解决方案4】:

任何你不能做的理由

    var imgCurrent = 'img' + imgLocate;

?从脚本中动态生成/执行代码基本上不是一个好主意。调试几乎是不可能的,而且你甚至没有真正做任何没有 eval 就无法完成的事情。

【讨论】:

  • 因为他想要变量img1的值,而不是字符串img1
最近更新 更多