纯JavaScript onclick在分配函数作用域结束后变为未定义

pure javascript onclick becomes undefined after assigning functions scope ends

本文关键字:结束 未定义 作用域 函数 JavaScript onclick 分配      更新时间:2023-09-26

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

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

初始化模板程序时首次调用此函数。第一次正常工作。但是,在将一些 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>

当我控制台.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]);
        }
    }
}

我安慰.log在replace_link范围像以前一样结束后,这次我仍然得到:

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

我真的很感激任何帮助和/或建议!如果我缺少任何有用的东西,请告诉我。

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

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

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

我的观点是,如果你改变innerHTML,我假设这是你"将一些html附加到文档正文"的方式,浏览器会将DOM对象序列化为HTML,执行字符串连接,然后再次解析它。这会导致不再具有扩展的新对象,例如 onClickonClick是自定义属性;反正你的意思可能是onclick

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

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

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

这里有一个小提琴,展示了这一点。http://jsfiddle.net/k9d7b2ds/

更新:进行了一些额外的更改。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