I want to be able to assign default values to variables when I'm using prototyping for object creation.
When I try to assign default values to the variables they are always 'undefined'.
I have tried to find the answer but all the possible solutions I have tried dont work.
My questions are:
why do a variable that have I have initiated with a value has the value 'undefined'
how do I solve my problem?
(function() {
EmployeeNS = {};
EmployeeNS.Employee = function() {
var _firstName;
var _lastName;
var _employeeID = 'Unassigned';
}
EmployeeNS.Employee.prototype.setFirstName = function(fName) { this._firstName = fName; };
EmployeeNS.Employee.prototype.getFirstName = function() { return this._firstName; };
EmployeeNS.Employee.prototype.setLastName = function(lName) { this._lastName = lName; };
EmployeeNS.Employee.prototype.getLastName = function() { return this._lastName; };
EmployeeNS.Employee.prototype.setEmployeeID = function(employeeID) { this._employeeID = employeeID; };
EmployeeNS.Employee.prototype.getEmployeeID = function() { return this._employeeID; };
EmployeeNS.Worker = function() {
var _department;
}
EmployeeNS.Worker.prototype = new EmployeeNS.Employee();
EmployeeNS.Worker.prototype.constructor = Worker;
EmployeeNS.Worker.prototype.setDepartment = function(department) { this._department = department; };
EmployeeNS.Worker.prototype.getDepartment = function() { return this._department; };
})();
function createWorker() {
var x = new EmployeeNS.Worker();
x.setFirstName("John");
x.setLastName("Doe");
x.setDepartment("Transport");
var message = x.getFirstName()
+ " "
+ x.getLastName()
+ " (Department: "
+ x.getDepartment()
+ " / EmployeeID: "
+ x.getEmployeeID()
+ ")";
alert(message);
}
Thanks
you can simply make it to work by changing like this,
EmployeeNS.Employee = function() {
this._firstName;
this._lastName;
this._employeeID = 'Unassigned';
}
Try out this way , you can make those variables truly private by wrapping Employee ,
(function() {
EmployeeNS = {};
(function() {
var _firstName;
var _lastName;
var _employeeID = 'Unassigned';
EmployeeNS.Employee = function() {
}
EmployeeNS.Employee.prototype.setFirstName = function(fName) { _firstName = fName; };
EmployeeNS.Employee.prototype.getFirstName = function() { return _firstName; };
EmployeeNS.Employee.prototype.setLastName = function(lName) { _lastName = lName; };
EmployeeNS.Employee.prototype.getLastName = function() { return _lastName; };
EmployeeNS.Employee.prototype.setEmployeeID = function(employeeID) { _employeeID = employeeID; };
EmployeeNS.Employee.prototype.getEmployeeID = function() { return _employeeID; };
})();
(function() {
var _department;
EmployeeNS.Worker = function() {
}
EmployeeNS.Worker.prototype = new EmployeeNS.Employee();
EmployeeNS.Worker.prototype.constructor = Worker;
EmployeeNS.Worker.prototype.setDepartment = function(department) { _department = department; };
EmployeeNS.Worker.prototype.getDepartment = function() { return _department; };
})();
})();
Here is the jsfiddle
If you want instance properties, do it like this:
(function() {
EmployeeNS = {};
EmployeeNS.Employee = function () {
this._firstName = null;
this._lastName = null;
this._employeeID = 'Unassigned';
};
EmployeeNS.Employee.prototype.setFirstName = function(fName) {
this._firstName = fName;
};
})();
Related
How can i send parameter this to function.
Above options work in constructor :
selectors[i].onblur = this.validation;
But if in function Valid i call the selectors[i].validation, above solution will not working. Does Somebody know, how to call selectors[i].validation with parameter this??
For any help, i will be very grateful.
link to demo:
http://codepen.io/anon/pen/YqryVr
My js classes:
var Validator = (function () {
var errorClassName = "error";
var selectors;
var regexMap;
function Validator(id, regexObject) {
if (id === void 0) { id = "form"; }
regexMap = regexObject.getMap();
selectors = document.getElementById(id).elements;
for (i = 0; i < selectors.length; ++i) {
selectors[i].onblur = this.validation;
}
};
Validator.prototype.setErrorClassName = function (className) {
errorClassName = className;
};
Validator.prototype.addClass = function (selector) {
if(selector.className.indexOf(errorClassName) < 1)
selector.className += " " + errorClassName;
};
Validator.prototype.removeClass = function (selector) {
selector.className = selector.className.replace(errorClassName, '');
};
Validator.prototype.validation = function () {
alert('this.type: ' + this.type);
switch(this.type) {
case 'textarea':
case 'text':
if(this.dataset.regex in regexMap) this.dataset.regex = regexMap[this.dataset.regex];
var pattern = new RegExp(this.dataset.regex);
if(this.value.length !== 0 && pattern.test(this.value)) {
Validator.prototype.removeClass(this);
return true;
} else {
Validator.prototype.addClass(this);
return false;
}
break;
case 'select-one':
if(this.value.length === 0) {
Validator.prototype.addClass(this);
return false;
} else {
Validator.prototype.removeClass(this);
return true;
}
break;
}
return true;
};
Validator.prototype.valid = function () {
for (i = 0; i < selectors.length; ++i) {
selectors[i].validation;
}
return true;
};
return Validator;
}());
var SelectorAttribute = (function () {
function SelectorAttribute(name, regex) {
this.name = name;
this.regex = regex;
}
SelectorAttribute.prototype.toString = function () {
return "name: " + this.name + ", regex = " + this.regex;
};
return SelectorAttribute;
}());
var StandardRegexPatterns = (function () {
var map = {};
function StandardRegexPatterns() {
map['zip-code-poland'] = '^[0-9]{2}-[0-9]{3}$';
map['phone-number-poland'] = '^[0-9]{9}$';
map['digits'] = '^[0-9]+$';
map['alpha'] = '^[a-zA-z]+$';
map['email'] = '^[-a-z0-9~!$%^&*_=+}{\'?]+(\.[-a-z0-9~!$%^&*_=+}{\'?]+)*#([a-z0-9_][-a-z0-9_]*(\.[-a-z0-9_]+)*\.(aero|arpa|biz|com|coop|edu|gov|info|int|mil|museum|name|net|org|pro|travel|mobi|[a-z][a-z])|([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}))(:[0-9]{1,5})?';
map['login'] = '^[a-z0-9_-\.]{3,21}$';
map['ip-address'] = '^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$';
map['url-address'] = '^((http[s]?|ftp):\/)?\/?([^:\/\s]+)((\/\w+)*\/)([\w\-\.]+[^#?\s]+)(.*)?(#[\w\-]+)?$';
}
StandardRegexPatterns.prototype.getMap = function () {
return map;
};
return StandardRegexPatterns;
}());
$( document ).ready(function() {
var validator = new Validator('form', new StandardRegexPatterns());
validator.setErrorClassName("error");
//var pattern = new StandardRegexPatterns();
// alert(Object.keys(pattern.getMap()));
$("button").on('click', function(){
alert(validator.valid());
});
});
You can use the following:
functionname.apply(this, [arguments]);
or
functionname.call(this, argument1, argument2);
if you don't have arguments you can just omit them.
I usually just do this:
funcitonname.apply(this, Arguments);
if I'm calling this method from within a function already so I can carry on the arguments to the functionname().
Learn more about apply
Learn more about call
I am trying to build a function that creates a person by receiving at first a full name and using methods to set the first, last and full name. Afterwards it would have methods that should be able to change each part of the name.
My current code looks like this:
var Person = function(firstAndLast) {
var name = firstAndLast;
this.getFirstName = function() {
return name.substr(0,name.indexOf(' '));
};
this.getLastName = function() {
return name.substr(name.indexOf(' ')+1);
};
this.getFullName = function() {
return name;
};
this.setFirstName = function() {
return name;
};
this.setLastName = function() {
return name;
};
this.setFullName = function() {
return name;
};
};
var bob = new Person('Bob Ross');
bob.setFullName();
Now I am completely stuck when it gets time to pass a new name, so that if I do something like:
bob.setFullName('George Carlin');
and then pass:
bob.getFullName();
I should get the answer 'George Carlin'.
yet this isn't happening.
Thanks as always.
So the problem was that I wasn't really understanding how the values where being passed, and that instead of working on a full name I should be working on the parts.
var Person = function(firstAndLast) {
var firstName = firstAndLast.split(' ')[0];
var lastName = firstAndLast.split(' ')[1];
this.setFirstName = function(firstNameNew) {
firstName = firstNameNew;
};
this.setLastName = function(lastNameNew) {
lastName = lastNameNew;
};
this.setFullName = function (fullNameNew) {
firstName = fullNameNew.split(' ')[0];
lastName = fullNameNew.split(' ')[1];
};
this.getFullName = function() {
return firstName + ' ' + lastName;
};
this.getFirstName = function() {
return firstName;
};
this.getLastName = function() {
return lastName;
};
};
var bob = new Person('Bob Ross');
I need to use logic like visitor pattern and I've created new
sample which failed in visitor.visit(self); and I got error undefined is not a function,
any idea what am I missing?
var Entity = function (file,name) {
var self = this;
var name;
var type;
var log = {};
this.setName = function (name) {
this.name = name;
};
this.accept = function (visitor) {
visitor.visit(self);
};
this.getName = function () {
return name;
};
this.getType = function () {
return type;
};
this.getLog = function () {
return log;
};
};
//Start using visitor
var verifyFile = function () {
this.visit = function (file) {
alert("test");
};
};
function test(){
var file = new Entity();
file.accept(verifyFile);
};
You are injecting a function that defines a function, but your code is looking for an object that contains a function - see below
var Entity = function(file, name) {
var self = this;
var name;
var type;
var log = {};
this.setName = function(name) {
this.name = name;
};
this.accept = function(visitor) {
visitor.visit(self);
};
this.getName = function() {
return name;
};
this.getType = function() {
return type;
};
this.getLog = function() {
return log;
};
};
//Start using visitor
var verifyFile = {
visit : function(file) {
alert("test");
}
};
function test() {
var file = new Entity();
file.accept(verifyFile);
};
test()
How can I get the latest page data (HTML & Javascript varaibles) from PhantomJS
e.g page.refresh() or something?
I have an Interval, than checks a variable (on the page) every 200ms. However, this variable and the page content, isn't shown to have changed over time. (even though I know it has)
So I need an efficient way to check the value of a JS variable every 200ms or so,
then once I've discovered that variable has changed value, I want to request the latest page HTML.
How can I do this?
var Error = function (description) {
this.description = description;
return this;
};
var DTO = function (status, content, error) {
this.status = status;
this.content = content;
this.error = error;
return this;
};
function outputAndExit(dto) {
console.log(JSON.stringify(dto));
phantom.exit();
}
//For any uncaught exception, just log it out for .NET to capture
window.onerror = function (errorMsg, url, lineNumber) {
var description = 'window.onerror caught an error: ' +
'errorMsg: ' + errorMsg +
'url: ' + url +
'lineNumber: ' + lineNumber;
outputAndExit(new DTO(false, null, new Error(description)));
};
var GetDynamicPageResult__ = function () {
var obj = new GetDynamicPageResult();
obj.initialize();
return obj;
};
var GetDynamicPageResult = function () {
var self = this;
this.initialize = function () {
this.error = null;
this.isContentReadyForCrawler = false;
this.ticker = null;
this.tickerInterval = 150;
this.tickerElapsed = 0;
this.url = '';
this.loadDependencies();
this.processArgs();
this.openPage();
};
this.loadDependencies = function () {
this.system = require('system'),
this.page = require('webpage').create(),
this.page.injectJs('jquery-1.10.2.min');
this.fs = require('fs');
};
this.processArgs = function () {
if (this.system.args.length == 0) {
outputAndExit(new DTO(false, null, new Error('No arguments given')));
}
//system.args[0] Was the name of this script
this.url = this.system.args[1];
};
this.updateIsContentReadyForCrawler = function () {
var updateIsContentReadyForCrawler = self.page.evaluate(function () {
self.isContentReadyForCrawler = window.isContentReadyForCrawler;
});
};
this.openPage = function () {
self.page.open(this.url, function (status) { //NB: status = 'success' || 'fail'
if (status !== 'success') {
outputAndExit(new DTO(false, null, new Error('page.open received a non-success status')));
}
self.initTicker();
});
};
this.initTicker = function () {
this.ticker = setInterval(self.handleTick, self.tickerInterval);
};
this.handleTick = function () {
self.tickerElapsed += self.tickerInterval;
self.updateIsContentReadyForCrawler();
if (self.isContentReadyForCrawler) {
clearInterval(self.ticker);
var content = self.page.content;
self.finish(true, content, null);
} else {
var tooMuchTimeElapsed = self.tickerElapsed > 7000;
if (tooMuchTimeElapsed) {
clearInterval(self.ticker);
self.finish(false, null, new Error('Too much time elapsed'));
}
}
};
this.finish = function (status, content, error) {
content = content || '';
error = error || {};
outputAndExit(new DTO(status, content, error));
};
};
/**********************************************************************************/
/***************************** Helpers *****************************/
/**********************************************************************************/
var Utility__ = function () {
var obj = new Utility();
obj.initialize();
return obj;
};
var Utility = function () {
var self = this;
this.initialize = function () {
};
this.isEmpty = function (obj) {
var isEmpty = false;
(obj == undefined || obj == null) && (isEmpty = true);
return isEmpty;
};
this.isStringEmpty = function (str) {
var isEmpty = false;
isEmpty(str) && (isEmpty = true);
(isEmpty == false && $.trim(str) == '') && (isEmpty = true);
return isEmpty;
};
};
var getDynamicPageResult = new GetDynamicPageResult__();
I think you are almost there: you need to be using page.evaluate(), but currently only use it to get window.isContentReadyForCrawler. You need to use page.evaluate() to grab the latest HTML too.
I'm going to shamelessly paste in code from another answer (https://stackoverflow.com/a/12044474/841830):
var html = page.evaluate(function () {
var root = document.getElementsByTagName("html")[0];
var html = root ? root.outerHTML : document.body.innerHTML;
return html;
});
I'm trying to extend an Abstract object.
var Abstract = function() { code = 'Abstract'; };
Abstract.prototype.getCode = function() { return code; };
Abstract.prototype.getC = function() { return c; };
var ItemA = function() { code = 'ItemA'; c = 'a'; };
ItemA.prototype = Object.create(Abstract.prototype);
ItemA.prototype.constructor = ItemA;
var ItemB = function() { code = 'ItemB'; };
ItemB.prototype = Object.create(Abstract.prototype);
ItemB.prototype.constructor = ItemB;
var b = new ItemB();
console.log(b.getCode());
var a = new ItemA();
console.log(b.getCode());
console.log(b.getC());
The result:
ItemB
ItemA
a
Is there any particular reason why I'm getting ItemA's scope in ItemB instance? How can I fix it?
It is because you are using global variables. Fix it by using this keyword:
var Abstract = function() { this.code = 'Abstract'; };
Abstract.prototype.getCode = function() { return this.code; };
Abstract.prototype.getC = function() { return this.c; };
var ItemA = function() { this.code = 'ItemA'; this.c = 'a'; };
ItemA.prototype = Object.create(Abstract.prototype);
ItemA.prototype.constructor = ItemA;
var ItemB = function() { this.code = 'ItemB'; };
ItemB.prototype = Object.create(Abstract.prototype);
ItemB.prototype.constructor = ItemB;
Although in this case ItemB.getC() will return undefined.