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()
Related
Suppose I have a function called log which simply prints the given string.
Can I refactor my code so both of these function could work?
log("needsChange").doSomethingWithTheStringBeforePrintingIt();
log("perfectStringToPrint");
You can do something similar with nested class logics:
var log = (function() {
//Class
var _log = (function() {
function _log(message) {
this.message = message;
}
_log.prototype.doSomethingWithTheStringBeforePrintingIt = function() {
this.message = this.message.split("").reverse().join("");
return this;
};
_log.prototype.capitalizeFirstWord = function() {
this.message = this.message[0].toUpperCase() + this.message.substr(1);
return this;
};
_log.prototype.print = function() {
return this.message;
};
return _log;
}());
//Instancer function
return function log(message) {
//Return instance of class
return new _log(message);
};
})();
//Test
console.log(log("needsChange")
.doSomethingWithTheStringBeforePrintingIt()
.capitalizeFirstWord()
.print(), log("perfectStringToPrint")
.print());
If you are comfortable with promises, then you can do something like this:
var logger = (function() {
//Class
var _log = (function() {
function _log(message) {
var _this = this;
this.message = message;
this.promise = null;
this.promises = [];
this.promise = Promise.all(this.promises).then(function(values) {
console.log(_this.message); // [3, 1337, "foo"]
});
}
_log.prototype.reverse = function() {
var self = this;
this.promises.push(new Promise(function(resolve, reject) {
setTimeout(resolve, 0, (function() {
self.message = self.message.split("").reverse().join("");
})());
}));
return this;
};
_log.prototype.capitalizeFirst = function() {
var self = this;
this.promises.push(new Promise(function(resolve, reject) {
setTimeout(resolve, 0, (function() {
self.message = self.message[0].toUpperCase() + self.message.substr(1);
})());
}));
return this;
};
return _log;
}());
//Instancer function
return function log(message) {
//Return instance of class
return new _log(message);
};
})();
//Test
logger("needsChange").reverse().capitalizeFirst().reverse(); //Capitalizes last letter
logger("perfectStringToPrint");
This removes the need for a .print call.
I have made a library to solve this issue
https://github.com/omidh28/clarifyjs
I've got two object prototypes like this:
function Tag(name, description) {
this.name = name;
this.description = description || null;
}
function Category(name, description) {
this.name = name;
this.description = description || null;
}
Both of them are exactly the same, which seems awkward. Is it possible to merge them both into an object named 'Entity', and refer to them both by different names (the original 'Tag' and 'Category')?
This may be further complicated by the fact I need to refer to the current prototype name inside the prototype.
Tag.prototype.toJSON = function() {
return {
__type: 'Tag',
name: this.name,
description: this.description
};
};
How can I apply the same 'toJSON' extension to the 'Entity' object, but make sure it returns 'Tag' or 'Category' in the '__type' field, dependent on which object is being used?
I would do something like this:
Dummy = function () {};
Entity = function (name) {
this.name = name;
};
Entity.prototype.toString = function () {
return "My name is " + this.name + ".";
};
A = function () {
Entity.call(this, 'A');
};
Dummy.prototype = Entity.prototype;
Dummy.prototype.constructor = A;
A.prototype = new Dummy();
B = function () {
Entity.call(this, 'B');
};
Dummy.prototype = Entity.prototype;
Dummy.prototype.constructor = B;
B.prototype = new Dummy();
document.body.innerHTML = ""
+ (new A()) + "<br />"
+ (new B());
Here is a small function to make things cleaner (hopefully):
function Nothing () {};
function extend (Sup, proto) {
function Class () {
if (this.init) {
this.init.apply(this, arguments);
}
}
Nothing.prototype = Sup.prototype;
Nothing.prototype.constructor = Sup;
Class.prototype = new Nothing();
delete Nothing.prototype;
for (var k in proto) {
Class.prototype[k] = proto[k];
}
return Class;
}
Here is how to use it:
Entity = extend(Nothing, {
init: function (name) {
this.name = name;
},
toString: function () {
return "My name is " + this.name + ".";
}
});
A = extend(Entity, {
init: function () {
var sup = Entity.prototype;
sup.init.call(this, 'A');
}
});
B = extend(Entity, {
init: function () {
var sup = Entity.prototype;
sup.init.call(this, 'B');
}
});
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;
};
})();
i'm practicing with Javascript Inheritance, my first try is following code:
var base_class = function()
{
var _data = null;
function _get() {
return _data;
}
this.get = function() {
return _get();
}
this.init = function(data) {
_data = data;
}
}
var new_class = function() {
base_class.call(this);
var _data = 'test';
function _getData() {
return this.get();
}
this.getDataOther = function() {
return _getData();
}
this.getData = function() {
return this.get();
}
this.init(_data);
}
new_class.prototype = base_class.prototype;
var instance = new new_class();
alert(instance.getData());
alert(instance.getDataOther());
to that point i am really happy with my solution, but there is one problem
that i dont get resolved.
the "getDataOther" method don`t return the stored data from the base class,
because i cannot access the public "get" class from the protected "_getData" method in the new_class.
How can i get that running ?
Thanks in advance.
Ps.: Please excuse my poor English
If you comment out the this.init function (which overwrites the base_class _data field) and make the new_class's getData function just return _data, you should be able to get distinct variables.
var base_class = function()
{
var _data = null;
function _get() {
return _data;
}
this.get = function() {
return _get();
}
this.init = function(data) {
_data = data;
}
}
var new_class = function() {
var self = this; //Some browsers require a separate this reference for
//internal functions.
//http://book.mixu.net/ch4.html
base_class.call(this);
var _data = 'test';
function _getData() {
return self.get();
}
this.getDataOther = function() {
return _getData();
}
this.getData = function() {
return _data; //Changed this line to just return data
//Before, it did the same thing as _getData()
}
//this.init(_data); //Commented out this function (it was changing the base_class' data)
}
new_class.prototype = base_class.prototype;
var instance = new new_class();
alert(instance.getData());
alert(instance.getDataOther());
Your english is fine by the way :)
How can I get the YUI3 sendRequest applied to a Datasource to return predefined objects, instead of plain ones?
For example, I have this Base class with its methods:
function Student(id, name){
this.id = id;
this.name = name;
}
Context.prototype.setId = function(id){ this.id = id; };
Context.prototype.setName = function(name){ this.name = name; };
Context.prototype.getId = function(){ return this.id; };
Context.prototype.getName = function(){ return this.name; };
And I have this code that retrieves data from an API, normalizes it and returns data as objects:
var studApiDataSource = new Y.DataSource.Get({source: API_URL});
studApiDataSource.plug(Y.Plugin.DataSourceJSONSchema, {
schema: {
resultListLocator: "response.student",
resultFields: ["id","name"]
}
});
var myCallback = function(e) {
Y.Array.each(e.response.results, function(stud){
Y.log(stud.id+' '+stud.name);
}
}
studApiDataSource.sendRequest({
request: "?cmd=getStudents",
callback: {
success: myCallback,
failure: function (e) { }
}
});
The array of objects retrieved by studApiDataSource.sendRequest() and passed to myCallback are normal objects, with id and name properties. However, I want these to be Student objects, with their member functions too (getId, getName etc)
I'm not sure I fully understand, but you could do something like the following.
var studentJSON = "{\"id\": 17, \"name\":\"my name is\"}";
function Student(obj){
this.name = obj.name;
this.id = obj.id;
}
Student.prototype.setId = function(id){ this.id = id; };
Student.prototype.setName = function(name){ this.name = name; };
Student.prototype.getId = function(){ return this.id; };
Student.prototype.getName = function(){ return this.name; };
YUI().use('json-parse', 'json-stringify', function (Y) {
try {
var stud = new Student(Y.JSON.parse(studentJSON));
alert(stud.getId());
}
catch (e) {
alert(e);
}
});