0

I was attempting to make a function that sets multiple attributes to an HTML element. I used the code provided by a Stack Overflow user on this page

Setting multiple attributes for an element at once with JavaScript

If I use a for in loop, the binding of this is successful, but if I use a forEach it is not? Why is that?

This Works

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

This does not work

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

However if I don't modify the Element Object and just make a regular function with the ForEach loop it works just fine.

Simple Implementation

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

myDiv.attributeSetter({
    class: "coolDiv",
  style: {
    color: "#0110ff",
    border: "2px solid lime"
  },
  "data-order": "one",
  "html": "Cool Div"
}); 
5
  • have you tried changing the second-last line of your 'This does not work' example to }.bind(this)); Commented Dec 26, 2016 at 2:00
  • forEach is crap and slow, so.. yeah :). Commented Dec 26, 2016 at 2:00
  • @trevor Yeah, that works, but I was wondering why I have to do that. Sorry if this is a poor question. Commented Dec 26, 2016 at 2:02
  • 1
    You have to do it because you are passing a callback function to the .forEach(). You don't know when your callback will execute, so you use .bind(this) to create a copy of your callback function that will execute at a future time in the context of myDiv. Although @Deep has a solution that works (called lexical capture of 'this'), it is not the best or most correct way of solving your issue. If you want to learn a lot about how these things work, I suggest reading the 'You Don't Know JS' series of books by Kyle Simpson, online and free: github.com/getify/You-Dont-Know-JS Commented Dec 26, 2016 at 2:22
  • @trevor Thanks, great answer. Commented Dec 26, 2016 at 2:49

1 Answer 1

1

The second snippet with foreach does not work because inside foreach this does not point to the div but to the window object and that is why you are getting error this.setAttribute is not a function

Change the implementation like below.

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>

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks, I guess I should brush up on .bind(). I mainly use JavaScript for design mainly.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.