how to access "this" object in javascript? - javascript

How come in the code below, the second line is giving me an undefined error?
function DAO()
{
this.arrVariable = new Array();
this.getItem = getItem;
this.getItemQuery = getItemQuery;
}
function getItem(key)
{
dao.arrVariable[key]();
}
function getItemQuery(key, url, options, pollfrequency)
{
alert('hey');
}
var dao = new DAO();
dao.arrVariable['var1'] = function() { this.getItemQuery('a','b','c','d'); };
dao.arrVariable['var1']();
I want to be able to access the dao's getItemQuery as an object call. How do I do this?

In that context, this refers to arrVariable. You can instead refer to it as dao.getItemQuery() inside the function:
dao.arrVariable['var1'] = function() { dao.getItemQuery('a','b','c','d'); };

You can use apply or call here.
So, instead of
dao.arrVariable['var1']();
Use either
dao.arrVariable['var1'].apply(dao, /* array of arguments here */);
or
dao.arrVariable['var1'].call(dao, /* arguments here, separated by commas */);

dao.getItemQuery can access dao's property

THe this in function() { this.getItemQuery('a','b','c','d'); }; refers to function() not to DAO. You need to access DAO by:
dao.arrVariable['var1'] = function() { dao.getItemQuery('a','b','c','d'); };

Related

How to define the function prototype if the function is defined as an object property

I want to create an object containing various functions. How can I define functions in the prototype of a constructor function, if the constructor function is a property of an object?
I tried it like this:
var UTILS = {
MyFuncCtor1: function () {
},
MyFuncCtor1.prototype.MyFunc1 : function() {
}
}
but it does not work
sinsc UTILS is an object, defining a "left-side" value is actually defining a property in this object.
Therefor the above code has no real meaning since MyFuncCtor1.prototype.MyFunc1 is not a valid key.
Once possible proper way to do that would be:
function MyFuncCtor1() {
}
MyFuncCtor1.prototype.MyFunc1 = function() {
alert('MyFunc1')
};
const UTILS = {
MyFuncCtor1: new MyFuncCtor1()
}
UTILS.MyFuncCtor1.MyFunc1()
https://jsfiddle.net/kadoshms/87qdt63e/4/
You could do it in two steps. First you define your constructor function and append your prototype functions. The you define your object and set the constructor as a property.
function MyFuncCtor1() {
}
MyFuncCtor1.protptype.MyFunc1 = function() {
}
var UTILS = {
MyFuncCtor1: MyFuncCtor1
}

How do I use a string method inside a string prototype extension method

I have the following javascript method:
String.prototype.includesAny = function(search) {
var found = false;
search.forEach(function(str) {
if(this.toLowerCase().includes(str.toLowerCase())) {
found = true;
}
});
return found;
};
But it throws the error:
this.toLowerCase is not a function
I am thinking this is because this is not actually an instance of String at this point? Anybody knows the right way to do what I'm doing (and still use the prototype paradigm)?
In javascript this is function scoped, so creating a new function creates a new this.
Your forEach call has a callback, which is a function, and within that function this is no longer the string, but most likely the window
The solution is to simply store a reference to whatever this is in the outer function
String.prototype.includesAny = function(search) {
var found = false,
input = this;
search.forEach(function(str) {
if (input.toLowerCase().includes(str.toLowerCase())) {
found = true;
}
});
return found;
};
Array.forEach also has an optional thisArg that can be used
String.prototype.includesAny = function(search) {
var found = false;
search.forEach(function(str) {
if (this.toLowerCase().includes(str.toLowerCase())) {
found = true;
}
}, this);
return found;
};
Or even better, use Array.some
String.prototype.includesAny = function(search) {
return search.some(function(str) {
return this.toLowerCase().includes(str.toLowerCase());
}, this);
};
As a sidenote, extending native prototypes is generally a bad idea.
You're probably correct about this not being a string because you are in the foreach. So store an instance of this in a variable before entering the foreach and use that instead.
var stringToCheck = this;
search.forEach(function...
You need to save your this in other variable to use it in other functions scope.

jQuery: use dynamic object based on variable value

I have several objects and all of them have some methods that are called the same but do different things.
When I click a button, I want to call the init() method, but the
object is different based on what button I clicked.
Here is a snippet
$btn.on('click', function(e){
e.preventDefault();
var $trigger = $(this);
var objectName = $trigger.data('object');
/*
if objectName is 'user', I want to call user.init(),
if it's 'product' I want to call product.init() and so on...
right now i get an error if I call like his
*/
objectName.init($trigger);
});
Is it possible to dynamically call an object like this ? I know it is for its properties and methods, but I din't find anything about this issue.
Thank you.
It's better to do mapping
var entities = {
user: user,
entity: entity
}
var objectName = $trigger.data('object');
entities[objectName].init($trigger);
In case your objects (or functions) defined in the global scope, you can access them using the window object:
var funcT = function() {
console.log('funcT was called');
}
var objT = {
'a': 1,
'b': 2
}
function a() {
var funcName = 'funcT'
window[funcName]();
var objName = 'objT'
console.log(window[objName]);
}
a()
With window[variable] you can access variables based on another variable.
So all that you need to do is to replace objectName.init($tr‌​igger); with: window[objectName].‌​init();

Constructor for Javascript Objects

I am trying to create a JAvascript Object with a constructor and 2 methods. I am getting errors when I try to use the following code, what am I doing wrong? Specifically, it wont allow me to define the constructor function as shown below.
var Feed = {
templateDOM: '',
function(tDOM) {
this.templateDOM = tDOM;
},
loadFeed: function(feedPage, feedsPerPage) {
...
},
showFeed: function(data, tDOM, destination) {
...
}
};
You aren't creating a constructor function at all here. It is a plain object, only you forgot to provide a property name for the second value in it.
If you wanted to create a constructor function, it would look more like this:
function Feed(tDOM) {
this.templateDOM = tDOM;
}
Feed.prototype.loadFeed = function loadFeed(feedPage, feedsPerPage) {
};
Feed.prototype.showFeed = function showFeed(data, tDOM, destination) {
};
Which you can then invoke like:
var my_feed = new Feed("some value");
myFeed.loadFeed("some value", "some other value");
I don't think that you approach can take you where you want. In your case you make use of an object literal. How are you going to make use of constructor, when you have already created an object?
I think that the following would be more suitable:
// Define a cosntructor
function TemplateDom(tDom){
this.templateDOM = tDOM;
}
and then add to the prototype of you constructor the methods:
// Add to the prototype of your constructor the following two functions.
// So each object that will be created using this constructor would have
// defined also those two methods.
TemplateDom.prototype.loadFeed = function(feedPage, feedsPerPage) {
...
};
TemplateDom.prototype.showFeed = function(data, tDOM, destination) {
...
};
Then you can create an object like below:
var templateDom = new TemplateDom("here you pass a dom value");
and you can use the functions loadFeed and showFeed as simple as
templateDom.loadFeed("feedpage value","feedsperpage value");
templateDom.showFeed("data value","tDom value","destination value");

Accessing properties in parent class

I am trying to make a parent data access layer class that is inherited by multiple classes.
parent class:
var DataAccess = function() {
this.Save = function(){
alert(this.ListName); //works
SaveLogic(this.Id); //doesnt work
}
}
Child Class:
var Job = function(){
Job.prototype.ListName = 'MyList'; //works
this.Save = function(){
Job.prototype.Save().call(this);
//specific Job Save logic
}
}
Job.prototype = new DataAccess();
Now in my main class:
var aJob = new Job();
aJob.Id = 1;
aJob.Save(); //Does not work. Prototype can not see aJob.Id..
As you can see, I need to create a parent function with shared variables such as ID, so when I inherit the parent class, I can assign values to these variables so the shared logic of hte parents class work, then my extended class's can have specific logic
You can start with construction like this:
var DataAccess = function() {
this.Save = function(){
console.log('DataAccess Save call', this.ListName, this.Id);
}
}
var Job = function(){
this.ListName = 'MyList';
}
Job.prototype = new DataAccess();
/**
* Delete me to use parent's Save method.
*/
Job.prototype.Save = function(){
console.log('Job Save call', this.ListName, this.Id);
}
var aJob = new Job();
aJob.Id = 1;
aJob.Save();
#stivlo described how it works in his answer here: https://stackoverflow.com/a/4778408/1127848
The problem I had was I wanted to reuse the same code. I think I have worked it out this way, im still not 100% its the right way to go with prototype programming :
function DataAccess() {
//setup common variables
}
DataAccess._Save_(listname, id){
commonSaveLogic(id);
doStuff(listname);
}
function Job() {
this.ListName = 'Jobs';
DataAccess.call(this); //call DataAccess Constructor
}
Job.prototype = DataAccess;
Job.prototype.constructor = Job;
Job.ProtoType.Save = function(){
this._Save_(this.ListName, this.Id);
}
function AotherList() {
this.ListName = 'AnotherList';
DataAccess.call(this);
}
//same as above. Job and Another list both inherit off DataAccess.
Dont use .prototype inside the constructor. We define .prototype for sharing same copy to all objects.
You are missing here many things. I'm explaining one by one:
First : SaveLogic(this.Id); //doesnt work
Because You don't use this with the function so it's a global function not a constructor function. And you don't have defined it any where so there will be an error like function SaveLogic not defined
To prevent this error, define the function somewhere.
Second : You have passed this.Id as a parameter. Id using the line aJob.Id = 1; will not be accessible within the SaveLogic(this.Id); because Id is a property of aJob not of ajob.prototype. this.ListName will be available here because it's a property of prototype.
So it you want to get Id inside SaveLogic() function, define it as prototype property.
Third : when this line aJob.Save(); will be invoke it will call
this.Save = function(){
Job.prototype.Save().call(this);
//specific Job Save logic
}
Job.prototype.Save() will search for a function named as Save(). Which is not defined in Job's prototype so function not defined error will occur.
Fourth : call() can not be called anyhow excepts either DataAccess.call() or Job.call();
call() is just like the constructor call excepts it's first parameter get assigned to the constructor's this object.
Here i have improved your code. Just copy and paste it in your editor and see what is going here.
Try this :
function SaveLogic(Id)
{
alert(Id);
}
var DataAccess = function() {
this.Save = function(){
alert(this.ListName); //works
SaveLogic(this.Id);
return this; //doesnt work
}
this.call = function() {
alert('call is called here');
}
}
var Job = function(){
Job.prototype.ListName = 'MyList'; //works
this.Save = function(){
//console.log(Job.prototype.Save());
Job.prototype.Save().call(this);
//specific Job Save logic
}
}
Job.prototype = new DataAccess();
var aJob = new Job();
Job.prototype.Id = 1;
aJob.Save(); //Does not work. Prototype can not see aJob.Id..

Categories