JavaScript-在所有标记上循环,在每个标记上添加一个onclick

JavaScript-在所有标记上循环,在每个标记上添加一个onclick,javascript,Javascript,我有一个指向图像的链接列表,还有一个js函数,它获取(图像的)URL,并在调用该函数时将该图像放在页面上 我最初是在每个a中添加一个内联onlick=“showPic(this.getAttribute('href'))”,但我想分离出内联js。下面是我在页面加载时为每个a标记添加onclick的函数: function prepareLinks(){ var links = document.getElementsByTagName('a'); for(var i=0; i<links.

我有一个指向图像的链接列表,还有一个js函数,它获取(图像的)URL,并在调用该函数时将该图像放在页面上

我最初是在每个a中添加一个内联onlick=“showPic(this.getAttribute('href'))”,但我想分离出内联js。下面是我在页面加载时为每个a标记添加onclick的函数:

function prepareLinks(){
var links = document.getElementsByTagName('a');
for(var i=0; i<links.length; i++){
    var thisLink = links[i];
    var source = thisLink.getAttribute('href'); 
    if(thisLink.getAttribute('class') == 'imgLink'){
        thisLink.onclick = function(){
            showPic(source);
            return false;
        }
    }
}
}

function showPic(source){
var placeholder = document.getElementById('placeholder');
placeholder.setAttribute('src',source);
}

window.onload = prepareLinks();
函数prepareLink(){
var links=document.getElementsByTagName('a');

for(var i=0;iJavaScript没有块作用域,因此关闭的变量最终是最后分配给它的变量。您可以通过将其包装在另一个闭包中来解决此问题:

function prepareLinks() {
    var links = document.getElementsByTagName('a');
    for(var i = 0; i < links.length; i++) {
        var thisLink = links[i];
        var source = thisLink.getAttribute('href'); 
        if(thisLink.getAttribute('class') == 'imgLink') {
            thisLink.onclick = (function(source) {
                return function() {
                    showPic(source);
                    return false;
                };
            })(source);
        }
    }
}

我相信这会破坏与IE5或IE6的兼容性,但希望您不关心这两个=)

这是访问外部变量的循环内部事件处理程序的老问题

您的
变量在
单击
事件时从作用域链中拉出,然后,由于迭代正在完成,它被设置为最后一个
href
属性

你需要做两件事中的一件来打破僵局

最简单但许多浏览器不支持的方法是使用
let
,它允许您使用块范围

let source = thisLink.getAttribute('href'); 
.它在Firefox中有效,但在Chrome中无效

在2038年,当我们处理的时候,所有浏览器都实现了ES6,这将是解决这个问题的标准方法

与所有浏览器兼容的一种更难理解和实现的方法是使用一种模式打破闭包,例如

thisLink.onclick = (function(src) {
  return function(){
            showPic(src);
            return false;
        }
})(source);

.

Minitech的答案应该可以解决您的问题,即
变量由所有onclick处理程序共享

这样做是非常浪费的,没有必要为每个链接设置单独的处理程序。而且,如果动态添加任何链接,它将不起作用。事件委派是一种方法

function interceptLinks() {
   // Bad way to set onclick (use a library)
   document.onclick = function() {
     if (this.tagName.toUpperCase() != 'A' ) {
       return;
     }
     // Bad way to check if it contains a class (use a library)
     if (this.getAttribute('class') == 'imgLink') {
       showPic(this.getAttribute('href'));
       return false;
     }
   }
}

感谢所有的回复。事实证明我没有正确诊断问题,抱歉。实际上,使用新的var和annon.function在每个循环迭代中添加onclick是有效的(传递的href是正确的)。它不起作用,因为我是通过“imgLink”获取a标记的类,该类是我在删除内联onclick处理程序时从HTML中删除的(我现在在父级上获得它们的ID)。此外,我还需要使用“return!showPic(this.href);”来停止在单击时正常跟踪链接

工作代码:

function showPic(source){
var placeholder = document.getElementById('placeholder');
placeholder.setAttribute('src',source);
return true;
}

function prepareLinks() {
if(!document.getElementById('imgLinks')){ return false; };
var galLinks = document.getElementById('imgLinks');
var links = galLinks.getElementsByTagName('a');
for(var i=0; i<links.length; i++) {
    var thisLink = links[i];
    thisLink.onclick = function() {
        return !showPic(this.href);
    };
}
}

window.onload = function(){
prepareLinks();
}
函数showPic(源代码){
var placeholder=document.getElementById('placeholder');
占位符.setAttribute('src',source);
返回true;
}
函数prepareLink(){
如果(!document.getElementById('imgLinks'){return false;};
var galLinks=document.getElementById('imgLinks');
var links=galLinks.getElementsByTagName('a');

对于(var i=0;我不想使用jQuery并使其成为真正的一行程序?您的
窗口。onload
是错误的。这将分配
prepareLink()的返回
窗口的
load
事件@alex:good catch,甚至没有看到那一点kirk-谢谢,但这只需要是普通的js。@alex-谢谢,在我刚刚发布的解决方案中已经解决了这个问题。Block scope不会解决这个问题。另外,如果你只是从处理程序中获取源代码,你不需要创建所有额外的代码 scopes@JuanMendes:实际上,块作用域确实可以解决此问题。至于从处理程序获取它-已添加;)我仍然不同意,我认为块作用域无法修复它,
source
在与所有handlers@JuanMendes:这真的不重要。例如,它确实使用块作用域来解决问题。如果我更了解C,我就不会完全理解代码。但是你必须在其中添加一个新变量
j
例如,只要打印
i
就可以输出5…给我块作用域,这意味着一个变量在该块之外是不可访问的。一个块作用域变量可以被带到一个闭包中…:p
let
不是EcmaScript(现在),它是Mozilla的JavaScript,希望它能把它变成EcmaScriptsoon@JuanMendes .
function showPic(source){
var placeholder = document.getElementById('placeholder');
placeholder.setAttribute('src',source);
return true;
}

function prepareLinks() {
if(!document.getElementById('imgLinks')){ return false; };
var galLinks = document.getElementById('imgLinks');
var links = galLinks.getElementsByTagName('a');
for(var i=0; i<links.length; i++) {
    var thisLink = links[i];
    thisLink.onclick = function() {
        return !showPic(this.href);
    };
}
}

window.onload = function(){
prepareLinks();
}