Is there any ways to short-up such chain call?
if (obj && obj.prop && obj.prop.subProp1 && obj.prop.subProp1.subPropFunc) {
obj.prop.subProp1.subPropFunc();
}
The only alternative I can imagine is try-catch. Any other ideas?
*I really tired of writing these. It's much easier in coffeescript using ?..
This should work given your sample code (haven't tested "all cases", just a copy of your sample):
function propsExist(obj) {
if (!obj) return false;
for (var i = 1; i < arguments.length; i++) {
if (!obj[arguments[i]]) return false;
obj = obj[arguments[i]];
}
return true;
}
if (propsExist(obj, "prop", "subProp1", "subPropFunc")) {
obj.prop.subProp1.subPropFunc();
}
The method propsExist() takes a variable number of arguments, the first of which being the original object you want to check properties/functions on. It will iterate through the list of properties you send to it and check them in-order. If one doesn't exist, it will return false. If it makes it through the whole loop, it validated successfully!
If you always want to call the sub-property's function if it validates, you could also just change the propsExist function to call it instead of returning true (then rename the function to something like callIfValid(obj, ...)
Same idea as the previous post, just a different solution.
function checkChain(variablePath,startingPoint){
var check = startingPoint || window,
parts = variablePath.split("."),
i;
for (i=0;i<parts.length;i++) {
check = check[parts[i]];
if (!check) {
return null;
}
}
return check;
}
var foo = { bar : { cat : { says : function(x){ alert(x); } } } };
var test1 = checkChain("foo.bar.cat.says");
if (test1) {
test1("meow");
}
var test2 = checkChain("foo.bar.cat.bark");
if (test2) {
test2("burp");
}
var test3 = checkChain("cat.says",foo.bar);
if (test3) {
test3("huh?");
}
Related
I want return an empty object meanwhile the object equals to boolean false in my function.
Obviously,if I return {} like the code below,it equals to boolean true which cannot meet my request.
decodeAndParse: function (jsonStr) {
if (this.NaEptStr(jsonStr)) {
var result;
result = decodeURIComponent(jsonStr);
result = JSON.parse(result);
return result;
}
return false;
}
Is there any possible to solve this problem?
very thankful if anybody can help me solve this problem
Your code can be:
decodeAndParse: function (jsonStr) {
return this.NaEptStr(jsonStr)? JSON.parse(decodeURIComponent(jsonStr)) : {};
}
Then in the calling code you probably have something like:
var obj = foo.decodeAndParse(jsonStr);
if (obj) {
...
}
You could have a simple "emptyObj" test like:
function isEmptyObject(obj) {
return !!Object.keys(obj).length;
}
Then in the caller:
if (isEmptyObject(obj)) {
If you need to shim Object.keys, see MDN. Note that IE8 still has a significant user share (greater than 20% of desktop browsers according to netmarketshare) so don't ignore non–ES5 browsers.
make a function that counts keys in object
function isNotEmpty(obj){
var count = 0;
for (var k in obj) {
if (obj.hasOwnProperty(k)) {
++count;
}
}
return count ? true : false;
}
and modify your if to
if (isNotEmpty(this.NaEptStr(jsonStr)))
But the simplest way to check if required field in object is present
if(this.naEpStr(jsonStr).myRequiredField)
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.
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
I need to check if a property contains a property, right now I am using if statements like in the example
Heres an example object
var Foo = {
"bar" :
{
"foobar":
{
"barfoo":1
}
}
}
And I need to check if barfoo exists, but first I need to check if all the other properties are there, because they might not be depending if another function has been run or not. I can't really lessen the levels of this structure either so that isn't an option.
Currently I am doing something similar to this:
var d = Foo;
if (d) {
d = d.bar;
if (d) {
d = d.foobar;
if (d) {
d = d.barfoo;
if(d){
console.log(d);
}
}
}
}
You could do it all in one if statement:
if (d && d.bar && d.bar.foobar && d.bar.foobar.barfoo)
This works because the javascript stops checking the if statement if any of the elements fail, so it doesn't error with something like cannot check property of undefined.
Otherwise you could use a try catch statement:
var barfoo;
try{
barfoo = d.bar.foobar.barfoo
}
catch(e){
barfoo = null;
}
More robust solution: check in any depth of the object
var Foo = {
"bar": {
"foobar": {
"barfoo": {
"ddd": 1
}
}
}
};
function checkProps(obj) {
var ref = obj, arg, i;
for (i = 1; i < arguments.length; i += 1) {
arg = arguments[i];
if(ref.hasOwnProperty(arg)){
ref = ref[arg]
} else {
return false;
}
}
return true;
}
//the function takes the object to search as first parameter and any other properties [,prop1,prop2,...]
console.log(checkProps(Foo, 'bar', 'foobar', 'barfoo', 'ddd'));
You can just do a single if statement with && - which does short circuit evaluation.
if (d
&& d.hasOwnProperty('bar')
&& d.bar.hasOwnProperty('foobar')
&& d.bar.foobar.hasOwnProperty('barfoo')
) {
// fancy things happen
}
The reason you use d.hasOwnProperty('bar') instead of just d.bar is in case something has polluted the object prototype.
If all you need to know is whether or not it exists, you could just do it with a try/catch
try{
if (Foo.bar.foobar.barfoo) {
//do stuff with your thingy because you know it exists
}
} catch(x) {
//you know it's no good/doesn't exist
}
When calling my function checkIss(), issFullArray.indexOf(issToCheck) always returns undefined. I've run a .length, output the contents of issFullArray, I can't figure out why it's not working- the array looks fine to me. As you can see below, I've tried explicitly setting issArray as an array and copying the array returned by my getIssList()
function updateIss() {
var issArray = [];
var currService = current.u_business_service;
var currIss = current.u_is_service;
issArray = getIssList(currService).slice(); //getIssList() returns an arry
if (checkIss(issArray, currIss) === false) {
//do stuff
}
}
function checkIss(issFullArray, issToCheck) {
if (issFullArray.indexOf(issToCheck) < 0) {
return false;
} else {
return true;
}
}
Easiest to just loop through the array and compare each value and return true if there is a match otherwise return false. Not much more code and works for all browsers.
function checkIss(issFullArray, issToCheck) {
for(i=0; i<issFullArray.length; i++) {
if(issFullArray[i]==issToCheck) {
return true;
}
}
return false;
}