【问题标题】:Why this doesn't bind using forEach, but does bind using a for in loop?为什么这不使用 forEach 绑定,而是使用 for in 循环绑定?
【发布时间】:2016-12-26 10:03:33
【问题描述】:

我试图创建一个为 HTML 元素设置多个属性的函数。我在此页面上使用了 Stack Overflow 用户提供的代码

Setting multiple attributes for an element at once with JavaScript

如果我使用for in 循环,this 的绑定是成功的,但如果我使用forEach 不是?这是为什么呢?

这可行

Element.prototype.attributeSetter = function(attrs){
  for(var prop in attrs){
    if((prop == "style" || prop == "styles") && (typeof attrs[prop] === 'object')){
        for(var n in attrs[prop]){
           this.style[n] = attrs[prop][n];
        }
    }else if(prop == "html"){
        this.innerHTML = attrs[prop];
    }else{
        console.log("this: ", this);
        this.setAttribute(prop, attrs[prop]);
    }
  }
}

这不起作用

Element.prototype.attributeSetter = function(attrs){
    Object.keys(attrs).forEach(function(prop){
      if((prop == "style" || prop == "styles") && (typeof attrs[prop] === 'object')){
         for(var n in attrs[prop]){
           this.style[n] = attrs[prop][n];
         }
      }else if(prop == "html"){
        this.innerHTML = attrs[prop];
      }else{
        //TypeError: this.setAttribute is not a function
        console.log("this: ", this);
        this.setAttribute(prop, attrs[prop]);
      }
  });
}

但是,如果我不修改元素对象,而只是使用 ForEach 循环创建一个常规函数,它就可以正常工作。

简单实现

var myDiv = document.getElementById("myDiv");

myDiv.attributeSetter({
    class: "coolDiv",
  style: {
    color: "#0110ff",
    border: "2px solid lime"
  },
  "data-order": "one",
  "html": "Cool Div"
}); 

【问题讨论】:

  • 您是否尝试过将“这不起作用”示例的倒数第二行更改为 }.bind(this));
  • forEach 很垃圾而且很慢,所以.. 是的 :)。
  • @trevor 是的,这行得通,但我想知道为什么我必须这样做。对不起,如果这是一个糟糕的问题。
  • 您必须这样做,因为您将回调函数传递给 .forEach()。您不知道回调何时执行,因此您使用 .bind(this) 创建回调函数的副本,该副本将在未来的时间在 myDiv 的上下文中执行。尽管@Deep 有一个有效的解决方案(称为“this”的词法捕获),但它并不是解决问题的最佳或最正确的方法。如果你想深入了解这些东西是如何工作的,我建议阅读 Kyle Simpson 的“你不知道 JS”系列书籍,在线免费:github.com/getify/You-Dont-Know-JS
  • @trevor 谢谢,很好的回答。

标签: javascript


【解决方案1】:

使用 foreach 的第二个 sn-p 不起作用,因为在 foreach 内部 this 不指向 div 而是指向 window 对象,这就是为什么你得到错误 this.setAttribute is not a function

如下所示更改实现。

Element.prototype.attributeSetter = function(attrs){
   var elem = this;
    Object.keys(attrs).forEach(function(prop){
      if((prop == "style" || prop == "styles") && (typeof attrs[prop] === 'object')){
         for(var n in attrs[prop]){
           elem.style[n] = attrs[prop][n];
         }
      }else if(prop == "html"){
        elem.innerHTML = attrs[prop];
      }else{
        //TypeError: this.setAttribute is not a function
        elem.setAttribute(prop, attrs[prop]);
      }
  });
}

var myDiv = document.getElementById("myDiv");

myDiv.attributeSetter({
    class: "coolDiv",
  style: {
    color: "#0110ff",
    border: "2px solid lime"
  },
  "data-order": "one",
  "html": "Cool Div"
});
 <div id="myDiv"></div>

【讨论】:

  • 谢谢,我想我应该复习一下.bind()。我主要使用JavaScript进行设计。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-27
  • 2018-09-18
  • 2015-06-17
  • 1970-01-01
  • 2011-04-21
  • 1970-01-01
相关资源
最近更新 更多