Why is my javascript object empty after constructing it - javascript

I use Knockout.js, and I have an object called letter in my script. That code looks as follows:
function letter(filePath, imagePath, countryId) {
self.filePath = filePath;
self.imagePath = imagePath;
self.countryId = countryId;
}
Then, another place in my code, the following snippet runs:
var uploadedLetter = new letter(data.key,'',59);
viewModel.letters.push(uploadedLetter);
I know that my data.key is a normal string value.
My viewModel code is like this:
var SendWindowedLetterViewModel = function(formSelector, data) {
var self = this;
self.letters = ko.observableArray([]);
}
Applying bindings on my view:
var createLetterData = {
};
var viewModel = new SendWindowedLetterViewModel('#sendLetterForm', createLetterData);
ko.applyBindings(viewModel, document.getElementById('sendLetterForm'));
However, when I look in FireBug after this line has been run, I have the following output:
And I cannot access any of my properties, and if I lookup the object in FireBug, it seems to be 100% empty.
Probably the most simple question ever asked on StackOverflow, but what am I overlooking here?

In letter, you use self.filePath = filePath.
But self isn't defined anywhere in its scope.
So you either do
function letter(filePath, imagePath, countryId) {
var self = this;
self.filePath = filePath;
self.imagePath = imagePath;
self.countryId = countryId;
}
or directly
function letter(filePath, imagePath, countryId) {
this.filePath = filePath;
this.imagePath = imagePath;
this.countryId = countryId;
}

Related

private object not setting data

Hi I'm trying to implement a LinkedList in Javascript. When i assign a value to my node it doesn't seem to store it when I use my getter. For example:
var Node =function() {
var _data;
var _next ={};
var that = this;
that.getData = function() {
return _data;
};
that.setData = function(data) {
that._data = data;
};
that.getNext = function() {
return _next;
};
that.setNext = function(next) {
that._next = next;
};
return that;
};
Will not work with:
var nodeObj = new Node();
nodeObj.setData("hello");
console.log(nodeObj.getData());
_data is not the same as that._data, you must do this:
that.getData = function() {
return that._data;
};
OR you could do this instead:
that.setData = function(data) {
_data = data;
};
the benefit of the second approach being that you're simulating a private variable (because you cannot do nodeObj._data in the second case but you can in the first)
also var that = this; is unnecessary, you can simply do this._data in this case.
For your case here, you can assume that if you're calling a function like yourObject.someFunction(), then within someFunction the value of this equals yourObject. (And this isn't always true in javascript but since you're starting off you should think about it this way for now. If you pass a function to another function as a variable and then call it then this wouldn't be the case).

Access object property within a callback

I wrote the following code:
var Request = require('./request');
function Treasure(id) {
Treasure.prototype.valid = false;
Treasure.prototype.id = id;
Treasure.prototype.contentLength = 0;
Treasure.prototype.title = null;
Treasure.prototype.seller = null;
Treasure.prototype.buyer = null;
Treasure.prototype.cost = 0;
}
Treasure.prototype.loadData = function() {
EpvpRequest.treasureRequest(Treasure.prototype.id, function(data) {
if (data.valid) {
Treasure.prototype.valid = data.valid;
Treasure.prototype.contentLength = data.contentLength;
Treasure.prototype.title = data.title;
Treasure.prototype.seller = data.seller;
Treasure.prototype.buyer = data.buyer;
Treasure.prototype.cost = data.cost;
}
});
}
module.exports = Treasure;
Please don't hit me, I just started learning javascript.
I want ot access the properties of "Treasure"; but I can't use this, because I have a callback in the loadData function and this would refer to the function which called the callback - is that correct?
But it seems that I can't access the properties the way I tried with Treasure.prototype.property.
What is the correct way to to this?
First of all, you should be assigning instance variables in the constructor instead of assiginng to the prototype. The prototype is for methods and other things that will be shared by all Treasure instances.
function Treasure(id) {
this.valid = false;
this.id = id;
this.contentLength = 0;
this.title = null;
this.seller = null;
this.buyer = null;
this.cost = 0;
}
As for your problem with this inside callbacks, the usual workaround is to store the value of this in a regular variable and then use that variable inside the callback.
Treasure.prototype.loadData = function() {
// Nothing special about "that"
// Its just a regular variable.
var that = this;
EpvpRequest.treasureRequest(that.id, function(data) {
if (data.valid) {
that.valid = data.valid;
that.contentLength = data.contentLength;
that.title = data.title;
that.seller = data.seller;
that.buyer = data.buyer;
that.cost = data.cost;
}
});
}
Since this pattern comes up very often, some people choose to always use the same name for the "this-storage" variable. Some of the more popular names are self and that.

NodeJS - How to assign constructor to module.exports in self-executing function?

I'm trying to assign a constructor in a self-executing function in NodeJS. I'm pretty sure it's not working because my parameter is a variable pointing to module.exports, but I'm curious if there's a way to make it work while staying as close to the self-executing format as possible.
Here's how the code is being called...
var TemplateEngine = require('./templateEngine');
templateEngine = new TemplateEngine({engine: 'swig'}); // "object is not a function"
Here's an example of code that works fine...
var assert = require('assert');
var swig = require('swig');
// Constructor
var TemplateEngine = function(args) {
assert.ok(args.engine, 'engine is required');
var templateEngine = {};
templateEngine.engine = args.engine;
templateEngine.Render = function(templateString, model) {
var result = swig.render(templateString, model);
return result;
};
return templateEngine;
};
module.exports = TemplateEngine;
and here's an example of the code style I'd like to use, but which produces a "TypeError: Object is not a function" error because I'm not actually assigning to module.exports, just a variable that copied whatever it was pointing to.
(function(templateEngine) {
var assert = require('assert');
var swig = require('swig');
templateEngine = function(args) {
assert.ok(args.engine, 'engine is required');
var templateEngine = {};
templateEngine.engine = args.engine;
templateEngine.Render = function (templateString, model) {
var result = swig.render(templateString, model);
return result;
};
return templateEngine;
};
})(module.exports);
Is there a way for me to use the above self-executing format and have my module export a Constructor?
In your second example, you are simply overwriting the templateEngine parameter, and that's not going to have any effect.
To get the same result as your first example, simply:
Pass module into your IIFE:
(function(module) {
})(module);
Assign a property to that:
(function(module) {
var assert = require('assert');
var swig = require('swig');
module.exports = function (args) {
...
};
})(module);

Assigning object retrieved by Parse.Query to a variable

I'm trying to do something that seems like it should be incredibly simple but have been searching for hours on end with no luck. I simply want to query a subclass of Parse.Object for a given objectId (ideally using .get() but .find or .first could work too) and assign that entire object to a variable I can access outside of the query. I understand that queries return promises and I am able to log the object I want to capture from inside of my .then() function but I can't figure out how to access it elsewhere. Here's what I have right now and I think I am on the right track.
var thisLunchQuery = new Parse.Query(Lunch);
var lunchIdTemp = this.model.get("lunchId");
thisLunchQuery.equalTo("objectId", lunchIdTemp);
var thisLunch = thisLunchQuery.find().then(function(results) {
console.log(results[0]);
});
This logs the entire object I want to access and I can see it's properties in the console. However, I would like to be able to access the "thisLunch" variable elsewhere in my code. As it stands, I can't do that. I'm assuming that's because of the scope of the variable. How can I define that variable in such a way that it gets a bigger scope
Here's a more comprehensive peace of code showing what I'm trying to do
render: function() {
var thisLunchQuery = new Parse.Query(Lunch);
var lunchIdTemp = this.model.get("lunchId");
function assignLunch(results){
//not sure what goes here
}
thisLunchQuery.equalTo("objectId", lunchIdTemp);
thisLunch = thisLunchQuery.find().then(assignLunch);
var templateArgs ={
thisPlans: this.model.toJSON(),
thisLunch: thisLunch
};
$(this.el).html(this.template(templateArgs));
return this;
this.delegateEvents();
}
As you can see, I'm trying to grab the object so I can pass it in to a template and access its attributes there. I hope this helps, I'm pretty new to all of this.
UPDATE:
Here's my best attempt at trying to chain queries so that I can use part of the result from the first one as a parameter for a second one and then use both queried for objects in the final callback function.
render: function() {
var thisLunchQuery = new Parse.Query(Lunch);
var thisLocationQuery = new Parse.Query(Location);
var lunchIdTemp = this.model.get("lunchId");
function assignLunch(results){
lunchObject = results[0];
thisLocationQuery.equalTo("objectId", results[0].get("locationId");
thisLocationQuery.find.then(assignLocation);
}
function assignLocation(locationResults, lunchObject){
// I'd like to be able to access the location I just found (locationResults[0]) as
//well as the original lunchId from the first query inside this callback
var templateArgs ={
thisPlans: this.model.toJSON(),
thisLunch: lunchObject,
thisLocation: locationResults[0];
};
$(this.el).html(this.template(templateArgs));
}
thisLunchQuery.equalTo("objectId", lunchIdTemp);
thisLunch = thisLunchQuery.find().then(assignLunch);
return this;
this.delegateEvents();
}
Obviously this doesn't quiet work but I'm not sure how to pass along data like I'm trying to. Maybe I should be using .when?
What you need to do is define a function that does what you want to do with your results, and pass it to the promise success method. Could look like this:
function doSomething(result) {
// do your stuff here
}
thisLunchQuery.find().then(doSomething)
UPDATE:
In the context of your view, the code could look something like:
render: function() {
var thisLunchQuery = new Parse.Query(Lunch);
var lunchIdTemp = this.model.get("lunchId");
var self = this;
function assignLunch(results){
var templateArgs = {
thisPlans: this.model.toJSON(),
thisLunch: results
};
self.$el.html(self.template(templateArgs));
}
thisLunchQuery.equalTo("objectId", lunchIdTemp);
thisLunchQuery.find().then(assignLunch);
return this;
}
You can either call a function with thisLunch as a parameter like:
var thisLunchQuery = new Parse.Query(Lunch);
var lunchIdTemp = this.model.get("lunchId");
thisLunchQuery.equalTo("objectId", lunchIdTemp);
var thisLunch = thisLunchQuery.find().then(function(results) {
funcName(results[0])
});
or put it in the global/window object like:
var thisLunchQuery = new Parse.Query(Lunch);
var lunchIdTemp = this.model.get("lunchId");
thisLunchQuery.equalTo("objectId", lunchIdTemp);
var thisLunch = thisLunchQuery.find().then(function(results) {
window.myLunch = results[0];
});

Define function for property of javascript class

I have this Javascript class and want to add some kind of function (like prototype)
to properties of this class.
function theUploader(virtualField)
{
var self = this;
//self.v = virtualField;
self.v = (function(){return self.v; this.clear = function(){self.v = '';}})()
self.v.prototype = function clear() {
self.v = '';
}
}
i tried those lines.
i couldn`t find out the right way to define such a thing.i want to call it like this
var temp = new theUploader('smart');
temp.v.clear();
someone guid me with jsaon.but still working on it
The problem(s) with this line:
self.v = (function(){return self.v; this.clear = function(){self.v = '';}})()
...would be more obvious if you split it out over several lines:
self.v = (function(){
return self.v;
this.clear = function(){
self.v = '';
}
})()
It's an immediately invoked function expression which returns on its first line, so it never gets to the this.clear = ... line. The value returned, self.v, will be undefined at that point, which means the self.v property you assign that value to will also be undefined, which means then on this line:
self.v.prototype = function clear() {
...you'll get an error TypeError: Cannot set property 'prototype' of undefined.
It's a bit hard to tell exactly what you're trying to do given the confusion in your theUploader() function, but given that you said you want to be able to do this:
var temp = new theUploader('smart');
temp.v.clear();
Then you need to create a .v property that is itself an object that has a .clear() method, so:
function theUploader(virtualField)
{
var self = this;
self.v = {}; // create a v property that is an object
self.v.clear = function(){self.v = '';}; // add a method to v
}
...would do it. Or you could define the clear function directly in the object literal:
self.v = {
clear : function(){self.v = '';}
};
(Either way it doesn't really make sense to me that calling self.v.clear() would actually overwrite the .v property with an empty string, but if that's what you want this is how you could do it.)
self.v.prototype = function clear() {
self.v = '';
}
Should be
self.v.clear = function() {
self.v = '';
}

Categories

Resources