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
4 Answers 4
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.
Comments
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);
3 Comments
divButton now is instance of custom Button "class" with .button property.button property and set this = document.createElement(tagName) inside function Button(tagName)?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 =)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);
3 Comments
this.button = button; and reference it in applyJsonProperties as this.button.style[cssAttribute] = jsonProperties[cssAttribute];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">
divButton.applyjSonProperties(props)wrong method namedivhere:document.createElement(div). You could simplify the code to betagName = tagName || 'div';on the first line.