Nesting Objects in Javascript - Anonymous is not a function error - javascript

Ok, so I'm a complete newbie to OOP in Javascript, apparently. I thought I understood it, but it appears I only know a small portion. Anyway, what I'm trying to do is setup an object to store and return data from an XML input by using a fairly simple string to retrieve data. I'd like to retrieve the data with a string similar to reader.getItem().getSubItem() or something like that.
Below is an example of what I attempted, but I get the error anonymous is not a function each time I try to do a call to fr.getType().isTexture() so obviously, I need to change something.
//Create the object by passing an XML element containing sub-elements
var fr = new FeatureReader(test.child(i));
alert(fr.getName()); //returns the object's name
alert(fr.getType().isTexture()); //"anonymous is not a function" error
function FeatureReader(feature) {
var feat = feature;
this.getName = function() {
return feat.name;
};
this.getType = new function() {
this.isTexture = new function() {
if (feat.type.texture == "yes") {
return true;
}
return false;
};
this.isModel = new function() {
if (feat.type.model == "yes") {
return true;
}
return false;
};
};
}
Now, obviously I could just remove the surrounding this.getType = function() {} around the this.isTexture and this.isModel to get my data, but for the sake of learning something, I'd like to see how it is recommended that I set this object up to get the returned values using a string similar to what I mentioned in the first and second paragraphs.

When you do this:
this.isTexture = new function() {
if (feat.type.texture == "yes") {
return true;
}
return false;
};
you're setting the "isTexture" property to the object constructed, not to that function. If you drop the new keyword from the statement, you'll be setting "isTexture" to be a function.
An expression of the form new <some-function> evaluates to an object, in other words.
edit — your "getType" property will also be an object, for the same reason. However, I think this would work:
alert( fr.getType.isTexture() );
Also note that your if statement can be simplified:
return feat.type.texture == "yes";

What you can do is simply assign an object instead of using new:
function FeatureReader(feature) {
var feat = feature;
this.getName = function() {
return feat.name;
};
this.getType = {
isTexture: function() {
return feat.type.texture == "yes";
},
isModel: function() {
return feat.type.model == "yes";
}
};
}
Then use the method like:
instance.getType.isTexture()
Note that you don't need to return true or false, as returning an expression that evaluates to boolean like a == b
returns a boolean value.

Related

Understand JSON result

In my code I have to analyse JSON objects. I use a small function set:
visit = function(object) {
if (isIterable(object)) {
forEachIn(object, function (accessor, child) {
visit(child);
});
}
else {
var value = object;
console.log(value);
}
};
forEachIn = function(iterable, functionRef) {
for (var accessor in iterable) {
functionRef(accessor, iterable[accessor]);
}
};
isIterable = function(element) {
return isArray(element) || isObject(element);
};
isArray = function(element) {
return element.constructor == Array;
};
isObject = function(element) {
return element.constructor == Object;
};
If I throw now a JSON Object to the visit function, it give me just the value to the console. But I expected the key/value combination. Example:
Code throw
aa03ddbffe59448fb8a56f6b80e650053
But I expect
uuid: aa03ddbffe59448fb8a56f6b80e650053
Is there anything I misunderstand?
I think the value variable must contain a different type from what you're expecting. You could try putting a breakpoint on that line of code and inspecting the object to check what it is. You're expecting the value variable to contain an object with a single uuid property, but it looks to me like the variable actually just contains a string.

Convert Javascript array back into JQuery-type object

For the code below, I wanted to make the _formsOk function work for both Javascript arrays and "JQuery objects". In function1(), I tried to create a Javascript array with all DOM elements except those that have a parent element with id="objectTypesContainer". Basically, function1() filters out the DOM elements I don't want before calling _formsOk() function, which does the actual form validation.
function1() {
var allForms = $('form:not(.vv_hidden)', this.selectMarketsContainer);
var nonObjectTypeForms = [];
allForms.each(function () {
if ($(this).parent().attr("id") !== "objectTypesContainer"){
nonObjectTypeForms.push($(this)[0]);
}
});
return this._formsOk(nonObjectTypeForms);
},
_formsOk: function($forms) {
var formOk = true;
console.log(typeof $forms)
$forms.each(function () { // This line fails
var validator = $(this).validate(DEFAULT_VALIDATION_OPTIONS);
if (!(validator && validator.form())) {
formOk = false;
}
});
return formOk;
},
However, I realized that because nonObjectTypeForms is now a JS Array rather than a "JQuery Object", the line marked (// This line fails) now fails.
The original code looked like this:
function1() {
var allForms = $('form:not(.vv_hidden)', this.selectMarketsContainer); // This is a "JQuery object", so no error occurs
return this._formsOk(allForms);
},
_formsOk: function($forms) {
var formOk = true;
console.log(typeof $forms)
$forms.each(function () { // This line fails
var validator = $(this).validate(DEFAULT_VALIDATION_OPTIONS);
if (!(validator && validator.form())) {
formOk = false;
}
});
return formOk;
},
Is there a way I can convert a JS array into a JQuery object ? I don't want to change _formsOk function definition just yet.
Instead of putting all elements in a new array, just use .filter() from the jQuery object.
allForms.filter(function () {
return $(this).parent().attr("id") !== "objectTypesContainer")
});
This will remove all the items you don't need in your selection and now allForms will only have the wanted elements.

JavaScript calling a getter from its function

Trying to do something that in pseudo code would look like this:
(function(scope) {
scope.doSomenthin = function() {
if (x === y && this.onfinish) {
// If exists, run onfinish, should return 'fin'
this.onfinish();
}
}
})(scope);
window.scope = window.scope || (window.scope = {});
scope.doSomenthin().onfinish = function(){return 'fin'}
At run time if onfinish exists, run that function. Tried using getters/setter but at that point it will return undefined. Setting a timeout works but its not something I wish to do.
Any other ideas? Thanks.
I'm not sure if I completely understand the question, but I think what you want comes down to setting the context for the functions you are calling. Is this what you are after?
//create a function that accesses an object's properties and methods with 'this'
var doSomethin = function() {
var result = "nonfinish";
if (this.onfinish) {
// If exists, run onfinish, should return 'fin'
result = this.onfinish();
}
return result;
}
//add an 'onfinish' method to the 'scope' object
scope = {
onfinish: function(){return 'fin'}
}
//run the accessor function in the window context
alert(doSomethin());
//run the accessor function in scope's context
alert(doSomethin.call(scope));
I see several mistakes with your code. This may be the results you are trying to achieve..
window.scope = window.scope || (window.scope = {});
scope.onfinish = function(){return 'fin'};
(function(scope) {
scope.doSomenthin = function() {
if (this.onfinish) {
// If exists, run onfinish, should return 'fin'
return this.onfinish();
}
}
})(scope);
alert(scope.doSomenthin());
When you create the temporary scope here you give scope as a
parameter. But scope is not defined yet.
(function(scope) {
scope.doSomenthin = function() {
if (x === y && this.onfinish) {
// If exists, run onfinish, should return 'fin'
this.onfinish();
}
}
})(scope);
Your scope.doSomenthin function doesn't return any value. Because
of that the value of scope.doSomenthin() is undifined. Therefore
with scope.doSomenthin().onfinish = function(){return 'fin'} you
are trying to set a property of undifined.
What you want to approach is similar to event-driven programming. Don't just call the function right away, register it as an event handler instead. The following pseudo-code only shows my idea. It's not complete
//register the function here, instead of calling it immediately
event = document.createEvent("HTMLEvents");
event.initEvent("myEvent", true, true);
document.addEventListener("myEvent", function(e) {
e.scope.doSomenthin = function() {
if (this.onfinish) {
// If exists, run onfinish, should return 'fin'
return this.onfinish();
}
}
});
......
//call the handler to handle the below event
window.scope = window.scope || (window.scope = {});
scope.doSomenthin().onfinish = function(){return 'fin'}
event.scope = scope;
document.body.dispatchEvent(event);
The above code is kind of silly. You have to design where to put and trigger the events.

How to call a function on string jQuery

I was reading through fluent api I got a doubt.
I want to take in a string upon which a jQuery function or example is called upon
Function
function compareThis(newString) {
function compare(newString) {
if (this == newString) {
alert("same string");
} else {
alert("differnt string");
}
}
}
Where it is called as
("alerting").compareThis("alerted").compare(); //alert 'different string'
I want to pass the data/string not as parameter but as called upon.
JSFiddle
Note: I would like to call the function in similar cases like finding date interval etc
You can use prototype to add function to String class:
String.prototype.compare = function(newString){
if (this == newString) {
alert("same string");
} else {
alert("differnt string");
}
};
I think you should adapt the code for your function, but it's the idea.
Maybe I missed interpreted however, it looks as it you required a form of method chaining to compare string. To do this you can create a variable and create functions inside it.
var compare = (function(){
var thisString;
var stringToCompare;
var create = function(sVal) {
thisString = sVal;
return this;
};
// Public
var compareThis = function(sVal) {
stringToCompare = sVal;
return this;
};
var compare = function(anotherString) {
return thisString == stringToCompare;
};
return {
create: create,
compareThis: compareThis,
compare: compare
};
}());
var b = compare.create('test').compareThis('test').compare();
alert(b);
Example fiddle

How to store variables: Privileged method, static property

Instead of just saying:
var thing = timeConsumingMethod();
I have my variable hidden in a method like so:
function _thing() {
var thing = timeConsumingMethod() );
return thing;
}
It gets called a number of times. I'm concerned that I'm made things very inefficient. I assume it calls timeConsumingMethod every time (which is unneeded, it's always the same) I call "_thing()" to get my variable.
How do I manage these types of variables in simple efficient way? Is something like this a solution?:
function _thing() {
return _thing.thing
}
_thing.thing = timeConsumingMethod();
Basically, i want the protection of a function and to (ideally0 access my variable using _thing() or something similar, but I only want timeConsumingMethod to run once.
edit: tried this, doesn't work either:
function _thingy() {
var thing = timeConsumingMethod();
}
_thingy.test = function() {
return( _thingy.thing)
}
Why not just:
function SomethingTimeConsuming() { ... }
function LazyThing(sourceFunction) {
this.sourceFunction = sourceFunction;
this.value = null;
this.Value = function() {
if ( this.value == null) this.value = sourceFunction();
return this.value;
}
}
JSFiddle: http://jsfiddle.net/YSAjJ/
Output:
[14:20:20.079] Calling time-consuming function *(1 time)

Categories