JavaScript的 - 如何让这段代码的工作? [重复](javascript - How

2019-09-02 10:55发布

这个问题已经在这里有一个答案:

  • JavaScript的闭包内环路-简单实用的例子 42个回答

代码给我:A B C

当我点击ABC它总是显示我的最后一个“伏特加”。 我想 “马丁”(对于A), “林赛”(对于B), “伏特加”(对于C)
请帮我在我的例子。

myArray = [
    {
        letter: "A",
        brand: "martin"
    },
    {
        letter: "B",
        brand: "lindsay"
    },
    {
        letter: "C",
        brand: "vodka"
    }
];
    var list = '';
    for (var i = 0; i < myArray.length; i++) {
    list += "<br>" + myArray[i].letter;

    new_info = myArray[i].link;
    (function(new_info) {
         $(this).click(function(){        //this - refers to A or B or C
                 $('#box2').text(new_info);
                 });
    }).call(this, myArray[i])
}

$('#box1').append(list);

Answer 1:

编辑:
我说我不打算写你的代码为你......嗯,我所做的: 这个小提琴确实你在寻找什么。 我解决了上下文(发行this ),闭合问题和隐含的全局。 它仍然需要大量的工作,但小提琴说明了什么大家一直说的: $(this) 不会,不能,也永远指向一个字符串常量像"A", or "B"

遗憾地这样说,但你的代码是完全的问题,但我会满足你问这里的具体问题。
在循环中,你要指定一个点击处理程序,基本上是这样的:

function()
{
    $('#box2').text(new_info);
}

其中new_info是在较高的范围内声明的变量。 到现在为止还挺好。 问题是,你正在创建没有自己的任何值变量( 拷贝函数对象new_info )发生的只是创建功能时举行。 相反,该函数引用变量。 因此,当任何这些功能被调用它$('#box2').text(new_info)将被解析为$('#box2').text("whatever value new_info holds when function is called")而不是$('#box2').text("whatever value new_info was holding when function was created") 您可以通过简单地添加第二个功能,你的代码给副本每个回调访问:

$(this).click((function(currentNewInfo)
{
    return function()
    {
        $('#box2').text(currentNewInfo);
    }
}(new_info)));

我正在这里做的是创造一个功能,那需要一个参数,并立即调用它。 我通过new_info作为参数,这样的价值currentNewInfo是什么new_info认为在那个时候(又名复印件)
我叫(IIFE - 或立即调用函数表达式)函数返回实际的回调。 在此回调,我不引用new_info ,但IIFE的说法: currentNewInfo

由于每个函数都有自己的范围内,该变量被封闭 (故名闭合 ),并且不能被访问或从外部改变。 仍然可以访问的唯一的事情currentNewInfo变量是IIFE返回的功能。
也许你担心名称冲突(每次创建回调使用引用currentNewInfo ),但事实并非如此:每次回调是由一个单独的函数创建的,因此可以访问不同的范围。 这是不可能有范围之间的名称冲突不互相访问...只是使事情非常简单的理解:

Where  /\            and      /\
       ||                     ||
  is return function()      is scope of IIFE

因此,关闭访问函数的作用域返回后。 该范围的优先级,当涉及到解析为一个值的表达式。 为了更好地理解,这里有一个类似的图给你看JS 如何解析表达式:


其中每一个粉红色的“外部环境记录”是一个功能的范围(即已经返回或函数当前功能的关闭范围被调用)。 最后的环境要么是全局对象,或者为空(在严格模式下)。 这里的所有都是它的。

老实说,闭包是棘手首先让你的头一轮,但一旦你掌握了我所要在这里解释,他们是伟大的乐趣。
检查此链接 ,我可以去解释的使用情况和效益,嵌套关闭工作的方式,但我最终会写一本书。 我张贴的链接做了伟大的工作,在解释关闭使用相当愚蠢的图纸是如何工作的。 它可能看起来幼稚,但他们实际上帮助我,当我试图抓住的lambda函数,关闭和范围外过着函数调用的概念很多。 以上是从页所采取的图我的联系,这也解释了概念更深入了一点,但我仍然认为简单的,原油图纸都会自行解释。

其他问题:
正如有人指出的:“你希望this参考”。 纵观片段, this将只是参考全局对象( window ),将相同/相似的事件处理程序window如果你问我根本就没有意义。
全局变量是邪恶的隐含的全局更是如此。 我看不到new_info ,也不myArray什么地方做声明。 JS解析表达式的方法是一点点遗憾,并回落到创建全局变量,没有这么多窥视:

var bar = 666;//global, always evil
function createGlobal()
{
    var local = 2;
    foo = bar * local;
}
createGlobal();

让我们来看看foo

JS is in createGlobal scope: var local is declared, and assigned 2.
   foo is used, and assigned bar*local
    ||                       ||   \\=>found in current scope, resolves to 2
    ||                       ||
    ||                       \\=>found in global scope, resolves to 666
    ||
    ||
    ||=> JS looks for foo declaration in function scope first, not found
    ||
    ||=> moves up 1 scope (either higher function, or global scope)
    ||
    \\=>Global scope, foo not found, create foo globally! - hence, implied global
             \\
              \\=>foo can now be resolved to global variable, value undefined

过多的DOM查询:你的事件处理程序回调看起来都像这样:

$('#box2').text(new_info);

这( $('#box2')实际上是一样的书写document.getElementById('#box2') 这实际上是英语。 想想看这样的:每个客户端点击时间$(this) -不管它可能是,你所访问的DOM,并与给定的ID扫描它的元素。 为什么不这样做一次 ,并使用保存在内存中的引用更改文本。 这不仅节省了无数的DOM queries.You 可以使用一个变量,或者(在我关于关闭解释光),封闭:

var list = (function(box2, list, i)
{//list & i are arguments, so local to scope, too
    for (i = 0; i < myArray.length; i++)
    {
        list += "<br>" + myArray[i].letter;//<-- don't know why you use this
        //new_info = myArray[i].link; no need for this var
        $(this).click((function(new_info)
        {//new_info is closure var now
            return function ()
            {//box2 references DOM element, is kept in memory to reduce DOM querying
                box2.text(link);
            };
        }(myArray[i].link));//instead of new_info, just pass value here
    }
    return list;//return string, assign to outer variable
}($('#box2'), ''));//query dom here, pass reference as argument


文章来源: javascript - How to make this code work? [duplicate]