在分配函数范围结束后,纯javascript onclick变为未定义

时间:2014-11-18 19:01:43

标签: javascript html

自从我在没有jQuery的情况下编写Javascript以来已经有一段时间了,所以请耐心等待。我假设我只是在做一些愚蠢的事情。我有这个函数将链接URL转换为我用我编写的路由器使用的内部表示。

Templater.prototype.replace_links = function() {
    this.links = document.getElementsByTagName("a");

    for (i = 0; i < this.links.length; i++) {
        if (!(this.links[i].getAttribute("href") === this.VOID && this.links[i].getAttribute(this.HREF))) {
            this.links[i].setAttribute(this.HREF, this.links[i].getAttribute("href"));
            this.links[i].setAttribute("href", this.VOID);
            this.links[i].onClick = function(self, link) {
                return function() { self.router.go(link.getAttribute(self.HREF)); };
            }(this, this.links[i]);
        }
    }
}

初始化Templater时第一次调用此函数。它第一次正常工作。但是,在我将一些html附加到文档正文后,我第二次运行它。我再次运行它,以防附加的html中也包含链接:

<body>
    <!-- arbitrary new html is loaded in here -->
    <a href="login">Login</a> <!-- becomes <a href="javascript:void(0)" lite-href="login">Login</a> correctly -->
    <a href="home">Home</a> <!-- becomes <a href="javascript:void(0)" lite-href="home">Home</a> correctly -->
</body>

当我在运行该函数但仍然在Templater函数中的console.log(this.links [0],this.links [0] .onClick)之后,我得到了正确的html然后undefined对于onClick事件:

<a href="javascript:void(0)" lite-href="discover">Discover</a> undefined 

当我将相同的内容记录到replace_links范围内的值时,我得到了我期待的内容。即功能显示:

<a href="javascript:void(0)" lite-href="Discover">Discover</a> function () { self.router.go(link.getAttribute(self.HREF)); }

我正在玩它,并尝试了这种方式并得到了同样的东西。

Templater.prototype.replace_links = function() {
    this.links = document.getElementsByTagName("a");

    for (i = 0; i < this.links.length; i++) {
        if (!(this.links[i].getAttribute("href") === this.VOID && this.links[i].getAttribute(this.HREF))) {
            (function(self, link) {
                link.setAttribute(self.HREF, link.getAttribute("href"));
                link.setAttribute("href", self.VOID);
                link.onClick = function() { self.router.go(link.getAttribute(self.HREF)); };
            })(this, this.links[i]);
        }
    }
}

在replace_link范围像之前一样结束之后我控制台.log这次我仍然得到:

<a href="javascript:void(0)" lite-href="discover">Discover</a> undefined

我非常感谢任何帮助和/或建议!如果我遗漏了任何有用的信息,请告诉我。

2 个答案:

答案 0 :(得分:2)

这里的关键点被视为次要细节。

  

我将一些html附加到文档正文中

  

this.links [i] .onClick = function(self,link){

我的观点是,如果你改变innerHTML,我认为这是你“将一些html附加到文档正文中的方式”,浏览器会将DOM对象序列化为HTML,进行字符串连接,然后再次解析它。这会导致新对象不再具有expandos,例如onClickonClick是自定义属性;无论如何,你可能意味着onclick

但是,您的一些更改将被成功序列化和解析,即setAttribute操作。因此,当您在HTML追加后运行replace_links时,

if (!(this.links[i].getAttribute("href") === this.VOID && this.links[i].getAttribute(this.HREF)))

check会将链接视为已替换,并且不会再次分配onClick

这是一个小提琴,显示了这一点。 http://jsfiddle.net/k9d7b2ds/

答案 1 :(得分:0)

更新:做了一些额外的更改。 onclick事件的默认this对象始终引用窗口对象。你需要通过关闭。

点击此处查看示例代码: http://jsfiddle.net/y0443fz6/

Templater.prototype.replace_links = function() {
    var that = this;
    this.links = document.getElementsByTagName("a");

    for (i = 0; i < this.links.length; i++) {
        if (!(this.links[i].getAttribute("href") === this.VOID && this.links[i].getAttribute(this.HREF))) {
            this.links[i].setAttribute(this.HREF, this.links[i].getAttribute("href"));
            this.links[i].setAttribute("href", this.VOID);
            this.links[i].onclick = function(self, link) {                
                return function() {
                  self.router.go(link.getAttribute(self.HREF)); 
                };
            }(that, this.links[i]);
        }
        console.log(this.links[i], this.links[i].onclick);
    }

}
希望有所帮助。 GL