1

The following code runs fine:

function Button(tagName) {
 var button;
 if (tagName) button = document.createElement(tagName);
 else button = document.createElement(div);
 button.innerHTML = 'Track Order';
 button.applyJsonProperties = function(jsonProperties){
 if(jsonProperties){
 for(var cssAttribute in jsonProperties){
 this.style[cssAttribute] = jsonProperties[cssAttribute];
 }
 }
 }
 return button;
}

The following code produces an error

function Button(tagName) {
 var button;
 if (tagName) button = document.createElement(tagName);
 else button = document.createElement(div);
 button.innerHTML = 'Track Order';
 return button;
}
Button.prototype.applyJsonProperties = function(jsonProperties){
 if(jsonProperties){
 for(var cssAttribute in jsonProperties){
 this.style[cssAttribute] = jsonProperties[cssAttribute];
 }
 }
}
var divButton = new Button('div');
var props = { "color" : "blue" }
divButton.applyJsonProperties(props); //returns undefined function
asked Jun 9, 2016 at 23:29
3
  • divButton.applyjSonProperties(props) wrong method name Commented Jun 9, 2016 at 23:37
  • 4
    The object returned from the Button function when called as a constructor is not an instance of Button, i.e. it doesn't inherit from Button.prototype because it returns a DOM Button element, not the constructor's this. Commented Jun 9, 2016 at 23:41
  • You're missing quotes around div here: document.createElement(div). You could simplify the code to be tagName = tagName || 'div'; on the first line. Commented Jun 10, 2016 at 0:15

4 Answers 4

1

Not sure what you are trying to do here. As you are explicitly returning a local variable button from the constructor function, the divButton = new Button('div') will be a div element like <div>Track Order</div>. This element obviously don't have acces to applyJsonProperties function.

answered Jun 9, 2016 at 23:45
Sign up to request clarification or add additional context in comments.

Comments

1

Because you return button in Button function.

And your applyjSonProperties returns nothing.

Try something like this:

function Button(tagName) {
 if (tagName) this.button = document.createElement(tagName);
 else this.button = document.createElement(div);
 this.button.innerHTML = 'Track Order';
}
Button.prototype.applyJsonProperties = function(jsonProperties){
 if(jsonProperties){
 for(var cssAttribute in jsonProperties){
 this.button.style[cssAttribute] = jsonProperties[cssAttribute];
 }
 }
 return this; //return modified (or not) instance
}
var divButton = new Button('div');
console.log(divButton.button);
var props = { "color" : "blue" }
divButton.applyJsonProperties(props);
console.log(divButton.button);

answered Jun 9, 2016 at 23:33

3 Comments

@RobG I updated answer. As you can see - divButton now is instance of custom Button "class" with .button property
is it possible to not have a .button property and set this = document.createElement(tagName) inside function Button(tagName)?
@guest, no, because this is reference to instance with his members, methods etc.. otherwise result of new Button(); will not be just created "DOM element" instead instance of Button. But you can return this.button in method (e.g. applyJsonProperties), and result of that method will be immediately "DOM element" instead instance of Button. (sorry for my English =)
1

Try adding this.button = button; and reference it in applyJsonProperties as this.button.style[cssAttribute] = jsonProperties[cssAttribute]; and remove return button :

function Button(tagName) {
 var button;
 if (tagName) button = document.createElement(tagName);
 else button = document.createElement('div');
 button.innerHTML = 'Track Order';
 this.button = button;
}
Button.prototype.applyJsonProperties = function(jsonProperties){
 if(jsonProperties){
 for(var cssAttribute in jsonProperties){
 this.button.style[cssAttribute] = jsonProperties[cssAttribute];
 }
 }
}
var divButton = new Button('div');
var props = { "color" : "blue" }
divButton.applyJsonProperties(props); 
answered Jun 9, 2016 at 23:57

3 Comments

Why should he try this? A good answer should explain what was wrong in the original code, and how the solution fixes it.
I'm sorry to say this, but there are only few line of codes and if you understand the question property you'll notice. Anyway, you can see in this answer, I have added this.button = button; and reference it in applyJsonProperties as this.button.style[cssAttribute] = jsonProperties[cssAttribute];
Put that explanation in the answer, not a comment.
0

When a function is called as a constructor, its this is initialised as a new Object that inherits from the constructor's prototype, i.e. the object's internal [[Prototype]] references the constructor's public prototype property.

When you return a different object (in the OP, a DOM HTMLButtonElement), then that object doesn't inherit from the constructor. e.g.

function Button(tagName) {
 var button = document.createElement(tagName || 'button');
 return button;
}
Button.prototype.applyJsonProperties = function(jsonProperties){};
var button = new Button();
console.log('button instanceof Button?: ' + (button instanceof Button)); // false
console.log('button.constructor: ' + button.constructor); // Not Button
console.log('Typeof button: ' + typeof button); // object
console.log('Typeof button.applyJsonProperties: ' + typeof button.applyJsonProperties); // undefined

As Rudolf Manusadzhyan suggests, you can have the element as a property of the instance and call methods on that, e.g.

function Button(tagName) {
 this.button = document.createElement(tagName || 'button');
}
Button.prototype.hide = function() {
 this.button.style.display = 'none';
}
Button.prototype.show = function() {
 this.button.style.display = '';
}
window.onload = function() {
 var button = new Button();
 button.button.textContent = 'The button';
 document.body.appendChild(button.button);
 document.getElementById('hideButton').onclick = function(){button.hide()};
 document.getElementById('showButton').onclick = function(){button.show()};
};
<input type="button" id="hideButton" value="Hide the button">
<input type="button" id="showButton" value="Show the button">

answered Jun 9, 2016 at 23:49

2 Comments

Thanks! this is very helpful!
How do you make sure that var button is an instance of Button in this case?

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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.