var ifChecks = function( i )
{
if( i === 23 )
{
// implementation
}
else if ( i === 300 )
{
// implementation
}
else if ...
}
I have this kind of long if else chain (app. 60 checks) in javascript code, this lengthy chain is inefficient as if 60th check comes as input, then it has to unnecessarily go through 59 checks, so I thought to implement like this.
var implobj = { 23 : handleimpl1,
300 : handleimpl2,
.
.
.
}
var handleImpl = function( i )
{
implobj[i]();
}
Is there any other way better than this solution which can be implemented in javascript?
Note: input is not sequential number, otherwise I could have used array instead of object.
I would use your idea, coded slightly differently like this:
var handleImpl = (function() {
var implobj = {
23 : handleimpl1,
300 : handleimpl2,
// ...
defaultImpl: someDefaultFn
}
return function(i) {
(implobj[i] || implobj.defaultImpl)();
};
}());
Related
Sample code with what I want to do is commented:
myObj.doSomething({
callbackFn: function( result ) {
if ( result && result.retval !== null )
{
// I want to assign the values on result.retval to myObj
// but `this` is not equal to myObj.
// is it correct to just do this?
myObj.some_val = result.some_val;
}
}
});
Normally with underscore, I'd use its _.bind() function to do this. The code I'm dealing with doesn't use underscore. What's the best way to do this with vanilla JS or jQuery?
JavaScript itself provides .bind:
myObj.doSomething({
callbackFn: function( result ) {
if ( result && result.retval !== null )
{
this.some_val = result.some_val;
}
}.bind(myObj); // <--
});
This is under the assumption that you cannot change the implementation of doSomething. If you can change it, see #10100111001's answer.
But you might as well use the code you currently have. I don't see a big benefit of using .bind here.
Just for fun, a simple version of.bind is pretty easy to implement yourself, should you find yourself in an environment that doesn't support it:
function bind(f, thisValue) {
return function() {
return f.apply(thisValue, arguments);
};
}
var boundF = bind(f, myObj);
You can also do something like this where you can call the callbackFn in doSomething with the proper this value.
var myObj = {};
myObj.doSomething = function (obj) {
obj.callbackFn.call(this, {some_val: "test"});
}
myObj.doSomething({
callbackFn: function( result ) {
if ( result && result.retval !== null )
{
// I want to assign the values on result.retval to myObj
// but `this` is not equal to myObj.
// is it correct to just do this?
this.some_val = result.some_val;
}
}
});
console.log(myObj);
with block is pretty much :
function( result ) {
if ( result && result.retval !== null )
{
with(myObj){
some_val = result.some_val; // Even,no Need "this"
}
}
}
Even, No need this
I work with javascript. Let's suppose I have the following function in my app:
function verify(cats) {
if ( cats > 20 ) {
// do something
}
}
Supposing i have a button to add cats, I may use that function after every cat adding.
However, i don't like this method.
I want that this function be in the background and is executed automatically when the condition states true
Is there some way to do so ?
Use a setter, that runs on every assignment. Before:
var obj = {};
obj.cats = 10;
obj.cats += 30;
verify(obj.cats); // we don't want to call this each time.
After:
var obj = {
_cats : 0, // private
get cats() { return this._cats; },
set cats(num) {
verify(num); // any verification here
this._cats = num;
}
};
Later, you can do:
obj.cats += 10; // will run verification
obj.cats = 15; // same
Alternatively, you can use a proxy, but those aren't really widely supported by JS engines yet.
How about setInterval()
$(function() {
setInterval(
function verify(cats) {
if ( cats > 20 ) {
// do something
}
}
, 10);
})
I notice that scan is missing from the various transducer libraries that I looked at (e.g transducers-js). Is it impossible to implement or am I missing something?
Actually I can answer my own question. I was trying to implement it in a functional way and I misunderstood how the transducer interface is used. Looking at the source code from transducers-js, they generally keep state in an object and I can implement scan the same way:
var Scan = function( agg, start, xf ){
this.xf = xf;
this.agg = agg;
this.accum = start;
}
Scan.prototype.init = function(){
return this.xf.init();
}
Scan.prototype.result = function(v) {
return this.xf.result(v);
}
Scan.prototype.step = function( result, input ) {
this.accum = this.agg( this.accum, input );
return this.xf.step( result, this.accum );
}
var scan = function(agg, start) {
return function (xf) {
return new Scan(agg, start, xf);
}
}
I'm a js developer and work in an environment where we do API calls and get some data returned. The structure of the data returned is HIGHLY inconsistent so therefor we can't assume anything about the data returned.
Picture the following scenario:
$.ajax({
success: function(data){
// Now I want to access a property 4 levels in
var length = data.results.users.length;
doSomeStuffWithLength(length);
}
})
What's the correct way to ensure data.results.users.length is not undefined? Because of the inconsistencies from the API, each level of the returned object could be broken/undefined. Do I really have to do the following:
if (data && data.results && data.results.users && data.results.users.length){
var length = data.results.users.length;
doSomeStuffWithLength(length);
}
Aren't there more elegant solutions?
You can create helper function like this.
Expect object with structure like this :
var someObj = {
some: {
other: {
third: 'bingo',
qwe: 'test'
}
}
};
Would be great to have something like
getPropByPath(someObj, 'some.other.qwe');
So the implementation of getPropByPath may looks like following:
function getPropByPath(obj, path){
var parts = path.split('.'),
root = obj;
for(var i=0; i<parts.length; i++) {
if(root[parts[i]] !== 'undefined') {
root = root[parts[i]]
} else {
return false;
}
}
return root;
}
If at all levels there may be something undefined, you should check all levels, something like:
var length = data &&
data.results &&
data.results.users &&
data.results.users.length || 0;
You can also use some helper function. Here's one:
function getPropValue ( path, defaultIfNotExisting ) {
defaultIfNotExisting = defaultIfNotExisting || 0;
path = path.split('.'), test = this;
while (path.length) {
test = test[path.shift()];
if (!test) {
return defaultIfNotExisting;
}
}
return test;
}
// usage in your case:
if ( getPropValue.call(data, 'results.users', []).length) { /* do stuff */}
On IE8 (not on IE9 or Safari) I get an error
this.text_array is null or not an object
for this line
`if( this.text_array[element].value === '' )`
for this object -
/**
* JClass - Text
*/
var Text = function( form_name )
{
this.text_array = document.forms[form_name].elements;
};
Text.prototype.patterns =
{
prefix_url: /^(http:)|(https:)\/\//,
url: /^.{1,2048}$/,
tweet: /^.{1,40}$/,
title: /^.{1,32}$/,
name: /^.{1,64}$/,
email: /^.{1,64}#.{1,255}$/,
pass: /^.{6,20}$/
};
Text.prototype.checkPattern = function( type )
{
return this.patterns[type].exec( this.text_array[type].value );
};
Text.prototype.checkUrlAdd = function( type )
{
return this.patterns[type].exec( this.text_array.url.value );
};
Text.prototype.checkSameEmail = function()
{
return ( (this.text_array.email.value) === (this.text_array.email1.value) );
};
Text.prototype.checkEmpty = function()
{
var element;
for ( element in this.text_array )
{
if( this.text_array[element].value === '' )
{
return 0;
}
}
return 1;
};
Not sure where to begin troubleshooting this. I guess I could start by hard coding the element object...that would eliminate the DOM Pull as a suspect. I could continue in this way...but I don't have IE8 available right now. Trial and Error unless someone has a bit of insight.
Related SO
for in vs. for
To start your debugging, use console.log(this.text_array); in relevant places.
I can only assume it's caused by this not being set right by the browser. In this case, start your checkEmpty function with var that = this; and use that instead of this through it.
Ended up using
document.getElementById()
for form access as a quick solution to fix the problem. Did not have time to troubleshoot further per suggestions.