V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
chiang
V2EX  ›  问与答

有个javascript的问题问问大家

  •  
  •   chiang · 2012-05-29 16:03:22 +08:00 · 3700 次点击
    这是一个创建于 4357 天前的主题,其中的信息可能已经有所发展或是发生改变。
    想写一个js功能通过点击不同的单词改变网页背景颜色,无奈无论点击哪个单词网页的背景都是红色。
    HTML片段和JS文件如下:




    效果图



    希望会的人解释一下原因,因为我实在想不出这里面哪里出错了,谢谢了。
    23 条回复    1970-01-01 08:00:00 +08:00
    sogood
        1
    sogood  
       2012-05-29 16:07:04 +08:00
    把 color 的赋值 移到 onclick 里面去。
    chiang
        2
    chiang  
    OP
       2012-05-29 16:12:26 +08:00

    这样的话,单击单词链接,背景色不会改变了。只是白色。
    allenm
        3
    allenm  
       2012-05-29 16:16:06 +08:00   ❤️ 1
    var color = this.getAttribute("title");
    试试看
    allenm
        4
    allenm  
       2012-05-29 16:16:32 +08:00
    放在 onclick 里边
    zythum
        5
    zythum  
       2012-05-29 16:19:01 +08:00   ❤️ 1
    @chiang 这个涉及到作用域的问题。
    尝试
    for(var i=0;i<links.length;i++){
    (function(i){
    links[i].onclick = ...
    })(i)
    }
    zzxworld
        6
    zzxworld  
       2012-05-29 16:19:10 +08:00   ❤️ 1
    粗略一看你的代码,就发现了问题所在,如果你把red链接移到blue上面去,点哪个都会是蓝色。javascript中变量是引用传递的,问题就在 var color=links[i].getAttribute('title');
    bit
        7
    bit  
       2012-05-29 16:21:12 +08:00   ❤️ 1
    5楼 @zythum 正解。闭包。推荐楼主看 JavaScript the Good Parts.
    zythum
        8
    zythum  
       2012-05-29 16:23:41 +08:00   ❤️ 1
    这个问题貌似js刚上手的童鞋都犯过这个错误。 没事没事。平常心。

    @bit @zzxworld 对把
    013231
        9
    013231  
       2012-05-29 16:24:30 +08:00   ❤️ 1
    bearice
        10
    bearice  
       2012-05-29 16:24:56 +08:00   ❤️ 1
    refs https://developer.mozilla.org/en/JavaScript/Reference/Statements/var#section_5

    我以前遇到这种问题都是吧for里面的代码放进一个匿名函数里执行,这样每次循环才会真正申明一个新的变量出来。
    chiang
        11
    chiang  
    OP
       2012-05-29 16:25:49 +08:00
    恩,谢谢各位。由于自己的js,也就刚刚吧 javascrip DOM编程艺术看完,就小小写一个,结果又是涉及到了一个书籍没有涉及的地方,下面一本书打算是 js权威指南,完全自学状态,所以有时候就会凭空想一些功能,然后自己来写。可是问题真是不少呢。
    maikcn
        12
    maikcn  
       2012-05-29 16:26:12 +08:00   ❤️ 1
    参数的作用域问题,将color转变成this就可以了,触发的对象可以直接this获取得到
    for(var i=0; i< links.length; i++) {
    links[i].onclick = function() {
    document.body.style.backgroundColor = this.getAttribute("title");
    }
    }
    Chris_Ys
        13
    Chris_Ys  
       2012-05-29 16:26:31 +08:00   ❤️ 1
    @zythum 说的作用域是问题所在,但是用闭包来处理就不够优雅了,个人推荐用事件代理:

    document.addEventListener('click', function(e){
    var el = e.target;
    if (el.tagName === "A") {
    // change color by title
    // if (el.getAttribute("title") === "blah blah") { ... }
    // switch (title) { case a: ... case b: ... }
    }
    }, false);
    chiang
        14
    chiang  
    OP
       2012-05-29 16:37:10 +08:00
    @013231 @mailkcn 的貌似在代码上来是挺整洁的。用现在学到的知识也能很好的理解。
    @zythum @bearice @Chtid_Yd 让我看到了更多
    ThanX ,还是第一次问这个问题,自己都拖自己好多时间没解决。
    Chris_Ys
        15
    Chris_Ys  
       2012-05-29 16:52:38 +08:00
    另外,如果有用 ES5 shim 或者只兼容 Chrome/Firefox/IE9+/... 或基于 V8 引擎(Node.js, PHP V8 ext, etc.) 的话,做循环建议用这样的方式:

    [].forEach.call(document.getElementsByTagName('a'), function(item, index){
    item.onclick = function(){
    document.body.style.backgroundColor = item.getAttribute("title");
    };
    });

    这是 100% 能避开作用域陷阱又保证代码优美的。

    建议 @chiang 了解一下 forEach、map 等函数。
    chiang
        16
    chiang  
    OP
       2012-05-29 17:05:33 +08:00
    @Chris_Ys 一切都在慢慢的进行中,谢谢你的指示,我都开始贪心要前辈多点指引了。虽然是一个web前端自学者,但是兴趣浓烈,做梦都会做到(汗 ,常常搞得早上很早就醒了。但是对整个前端的工作流程不是很了解,然后工具,测试,这些也还只是听过,没有了解。我喜欢做自己的东西,同时希望自己在各个方面都能学的踏实,能胜任工作。但不希望真的才在这个阶段就去去赶一些工程,变成纯码字的。如果能给我一些这方面建议,就感激不尽了。
    chiang
        17
    chiang  
    OP
       2012-05-29 17:07:45 +08:00
    对了各位,我是一名大三的学生,学习时间是相当充裕的,因为我很早的时候就决定把我自己的时间献给我喜爱的东西了。
    Chris_Ys
        18
    Chris_Ys  
       2012-05-29 17:34:20 +08:00   ❤️ 1
    @chiang 我个人的学习路线:

    - 无视 IE 等兼容性问题,一切走标准路线
    - 找一个开源的非 Ajax(每个链接都会刷新页面)、页面 UI 和交互非常简单的项目,todo 类是最容易找的
    - 看 javascriptkit.com、MDN 的文档,用 jQuery 往里堆功能
    - 能堆什么功能呢?以 todo 为例,打字的时候验证、改变 todo 的显示状态、插入 todo 时的效果、提交的 ajax、ajax 获取数据、对 todos 的遍历、todos 的全文检索、排序、添加 due date、添加 timer……
    - 能用 jQuery 搞定上面的功能,这时候差不多就会碰到新的问题:性能、代码是否乱七八糟
    - 尝试重构代码,尝试用原生语法和函数去解决性能问题,etc.

    选择 jQuery 的理由是语法简单,初学者不太深究运行机制的话,很快能做出一些东西。

    然后就是分水岭。

    停留在用库的地步,那也就到此为止。

    如果这时候你开始有用原生函数去解决一些问题的想法或提出疑问,比如 $(el).attr("id") 和 el.id 的区别在哪,这时候你就是真正踏足这个领域。

    再之后,就是 backbone、templating、requirejs、module 等。
    chiang
        19
    chiang  
    OP
       2012-05-29 17:46:26 +08:00
    @Chris_Ys 谢谢你。现阶段会把原生的js弄熟悉,然后在开始使用jQuery这些框架。刚刚上面应该改成学的“扎实”。(泪奔中...
    clowwindy
        20
    clowwindy  
       2012-05-29 23:35:30 +08:00
    imcotton
        21
    imcotton  
       2012-05-30 03:50:40 +08:00
    每到这种时候,我就忍不住要写 CoffeeScript
    http://gist.github.com/6bd4781bc7528a65c148
    imcotton
        22
    imcotton  
       2012-05-30 03:52:39 +08:00
    chiang
        23
    chiang  
    OP
       2012-05-30 07:41:03 +08:00
    @clowwindy @imcotton 问题已经解决了,谢谢你们
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   2186 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 02:13 · PVG 10:13 · LAX 19:13 · JFK 22:13
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.