javascript - 如何使这段代码工作? [英] javascript - How to make this code work?

查看:94
本文介绍了javascript - 如何使这段代码工作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

代码给了我:
A
B
C

Code gives me: A B C

当我点击ABC它总是显示我最后一个伏特加。
我想要martin(对于A),lindsay(对于B),vodka(对于C)

请帮助我的例子。

When I click on A B C it always shows me the last one "vodka". I want "martin" (for A), "lindsay"(for B), "vodka" (for C)
Please help me on my example.

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);


推荐答案

/>
我说我不会为你编写代码...好吧,我做了:这个小提琴确实是你要找的。我解决了上下文( this ),闭包问题和隐含全局的问题。它仍然需要大量的工作,但小提琴显示了大家一直在说: $(this) 不,不能,永远不会指向一个字符串常量像A或B


I said I wasn't going to write your code for you... well, I did: this fiddle does exactly what you're looking for. I solved the issue with context (this), closure issues and implied globals. It still needs a lot of work, but the fiddle shows what everybody has been saying: $(this) does not, cannot and will never point to a string constant like "A", or "B".

完整的问题,但我将解决您在这里询问的具体问题。

在循环中,您分配一个点击处理程序,基本上看起来像this:

Sorry to say this, but your code is full of problems, but I will address the specific issue you're asking about here.
Inside the loop, you're assigning a click handler that, basically looks like this:

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

其中 new_info 在较高范围中声明的变量。到现在为止还挺好。问题是,您创建的函数对象没有自己的 变量( new_info )的值该函数已创建。相反,函数引用该变量。所以当任何这些函数被调用它 $('#box2').text(new_info)将被解析为 $('#box2' ).text(当函数被调用时,值为new_info),而不是 $('#box2')。 )。您可以通过向代码中添加第二个函数来为每个回调访问 a copy

Where new_info is a variable that is declared in a higher scope. So far, so good. The problem is, the function object you're creating doesn't have its own copy of whatever value that variable (new_info) happened to hold when that function was created. Instead, the function references that variable. So when any of those functions is invoked it $('#box2').text(new_info) will be resolved to $('#box2').text("whatever value new_info holds when function is called"), not $('#box2').text("whatever value new_info was holding when function was created"). You can give each callback access to a copy by simply adding a second function to your code:

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

我在这里做的是创建一个函数,接受一个参数,并立即调用。我通过 new_info 作为参数,所以 currentNewInfo 的值将是 new_info 暂停(aka a copy)

我调用的函数(IIFE - 或Immediately Invoked Function Expression)返回实际的回调。在这个回调中,我不引用 new_info ,而是引用IIFE的参数: currentNewInfo

What I'm doing here is creating a function, that takes an argument, and calling it immediately. I pass new_info as an argument, so the value of currentNewInfo will be what new_info holds at that time (aka a copy)
The function I called (IIFE - or Immediately Invoked Function Expression) returns the actual callback. In this callback, I don't reference new_info, but the argument of the IIFE: currentNewInfo.

因为每个函数都有自己的作用域,该变量被括起来(因此名称为 closure ) ,并且不能从外部访问或改变。唯一仍然可以访问 currentNewInfo 变量的是IIFE返回的函数。

也许你担心名字冲突(你创建的每个回调都使用引用 currentNewInfo ),但事实并非如此:每个回调都是由一个单独的函数,因此可以访问不同的范围。在不能彼此访问的范围之间不可能存在名称冲突...只是为了使事情变得非常简单

Because each function has its own scope, that variable is enclosed (hence the name closure), and cannot be accessed or altered from outside. The only thing that can still access the currentNewInfo variable is the function the IIFE returned.
Perhaps you are worried about name-conflicts (each callback you create uses references currentNewInfo), but that's not the case: each callback was created by a separate function, and therefore has access to a different scope. It's not possible to have a name conflict between scopes that don't access each other... Just to make things really simple to understand:

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

因此,闭包可以访问函数的作用域后返回。当将表达式解析为值时,该范围具有优先权。为了更好地理解这一点,下面是一个类似的图表来显示你如何解析表达式:

So closures have access to a function's scope after it returns. That scope has precedence when it comes to resolving an expression to a value. To understand this better, here's a similar diagram to show you how JS resolves expressions:



其中每个粉红色的外部环境记录是函数的范围(函数的闭包范围返回已经或当前正在调用的函数)。最后一个环境将是全局对象,或null(在严格模式下)。


Where each pink "outer environment record" is a scope of a function (closure scope of a function that has returned already or function currently being called). The last environment will either be the global object, or null (in strict mode). That's all there is to it.

老实说,关闭起来很棘手,一开始你的头脑很好,但是一旦你掌握了我在这里解释的东西,他们是伟大的有趣。
$
查看此链接< a>我可以继续解释用例和好处,以及嵌套关闭的工作方式,但我最终会写一本书。我发布的链接在解释闭包如何使用相当愚蠢的图纸做一个伟大的工作。它可能看起来很幼稚,但是当我试图抓住lambda函数,闭包和范围的概念超出了函数调用的时候,它们实际上帮助了我很多。上面的图表是从我链接到的页面,这将解释了一些概念有点更深入,但我仍然认为简单,粗略的图纸是很自我解释。

Honestly, closures are tricky to get your head round at first, but once you grasp what I tried to explain here, they're great fun.
Check this link I can go on to explain the use cases and benefits and ways nested closures work, but I'd end up writing a book. The link I posted does a great job at explaining how closures work using rather silly drawings. It may seem childish, but they actually helped me a lot when I was trying to grasp the concept of lambda functions, closures and scopes out-living a function-call. The diagrams above are taken from the page I linked to, which explains the concepts a bit more in-depth, but I still think the simple, crude drawings are pretty self explanatory.

其他问题

正如有人指出:你期望 this 引用。查看代码片段,这个将引用全局对象( window ),附加相同/类似的事件处理程序 window 根本没有意义,如果你问我。
全局变量是 evil 隐含的全局变量。我看不到 new_info ,也没有在任何地方声明 myArray 。 JS解析表达式的方式是一个很不幸的,并回到创建全局变量,没有一个窥视:

Other issues:
As someone pointed out: "What are you expecting this to reference". Looking at the snippet, this will just reference the global object (window), attaching the same/similar event handler to window simply doesn't make sense if you ask me.
Global variables are evil, implied globals even more so. I can't see new_info, nor myArray being declared anywhere. The way JS resolves expressions is a tad unfortunate and falls back to creating global variables, without so much as a peep:

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查询:您的事件处理程序回调全部如下所示:

Excessive DOM queries: your event-handler callbacks all look like so:

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

此( $('#box2'))实际上与写 document.getElementById('#box2')相同。这几乎是英语。想象一下这样:每次客户点击 $(this) - 无论是什么,你正在访问DOM,并扫描它的元素与给定ID。为什么不这样做一次,并使用内存中的引用来更改文本。这可以节省无数的DOM查询。您可以使用一个变量,或者(根据我对闭包的解释),一个闭包:

This ($('#box2')) is actually the same as writing document.getElementById('#box2'). Which is practically English. Think about it like this: each time the client clicks on $(this) - whatever that may be, you're accessing the DOM, and scanning it for an element with a given ID. Why not do this once and use a reference kept in memory to change the text. That saves countless DOM queries.You could use a variable, or (in light of what I explained about closures), a closure:

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 - 如何使这段代码工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆