Define this function outside of a loop - javascript

I have the following code :
for (var entry in metadata) {
if (metadata.hasOwnProperty(entry)) {
var varName = metadata[entry].variableName;
if (metadata[entry].multipleValues === "false") {
if (angular.isDefined(vm[varName]) && (vm[varName] !== null) && vm[varName].id !== null) {
filters.push(factory.buildEntry(metadata[entry].variableName, vm[varName].id, null, factory.filterOperators.textContains));
}
} else {
if (angular.isDefined(vm[varName]) && (angular.isArray(vm[varName])) && (vm[varName].length > 0)) {
filters.push(factory.buildEntry(metadata[entry].variableName, null, vm[varName].map(function (item) {
return item.id;
}), factory.filterOperators.textContains));
}
}
}
}
But SonarQube keeps telling me to Define this function outside of a loop., and the only function I have inside this loop is the anonymous function I pass to the Array.prototype.map() method :
function (item) {
return item.id;
}
Which would be useless if I define it outside my loop since it's body only contains one line of code.
Why I'm getting this error ? and how can I tell SonarQube to skip it.

How about you define it outside the loop
var mapFunction = function (item) {
return item.id;
};
for (var entry in metadata) {
if (metadata.hasOwnProperty(entry)) {
var varName = metadata[entry].variableName;
if (metadata[entry].multipleValues === "false") {
if (angular.isDefined(vm[varName]) && (vm[varName] !== null) && vm[varName].id !== null) {
filters.push(factory.buildEntry(metadata[entry].variableName, vm[varName].id, null, factory.filterOperators.textContains));
}
} else {
if (angular.isDefined(vm[varName]) && (angular.isArray(vm[varName])) && (vm[varName].length > 0)) {
filters.push(factory.buildEntry(metadata[entry].variableName, null, vm[varName].map(mapFunction), factory.filterOperators.textContains));
}
}
}
}
You can assign functions to variables and then treat that variable as a function
var foo = function(){console.log('bar')};
foo();
In your case by assigning your mapping function to a variable, then passing that variable to the .map() gives you also an efficiency boost, because the function doesn't have to be re-instantiated every single time the loop runs. It can just re-use the same function over and over.
And as soon as the enclosing function ends which executes the loop, the variable ceases to exist.

Related

JS function removing old properties from object instead of adding to them

I created an object in JS called filterObj like this
var filterObj={};
The problem is that if I add property to the object, it adds but it removes the previous ones. In fact it takes the root filterObj which is empty, not the edited one.
In which I have two functions:
function handleGovernorate(Governorate) {
if (Governorate === "") {
return
}
else if (Governorate === "all") {
delete filterObj.governorate;
handleFilterObj();
return setFinalLocations(Locations);
}
else {
filterObj.governorate = Governorate;
handleFilterObj();
}
}
function handleGovernorate(District) {
if (District === "") {
return
}
else if (District === "all") {
delete filterObj.district;
handleFilterObj();
return setFinalLocations(Locations);
}
else {
filterObj.district = District;
handleFilterObj();
}
}
If I call handleGovernorate("mountLB") it sets the property governorate with value mountLB, but if I then call handleDistrict("2") the function will set a property district with value 2 but with removing the governorate property - why?

Trying to check if object exists in Knockout Observable Array

I'm trying to check if an object has the same observable values of other objects with the same observable properties inside an observable array.
I created a foreach loop which evaluates if any of the observables match. The problem I'm having is that condition always evaluates to true, even though these values are different. I'm using typescript and knockout.
Here's the code :
export function addPDFToPackage(heat: MTRHeat): void {
var koHeat: MTRHeatWithInclude = ko.mapping.fromJS(heat);
koHeat.Include = ko.observable(true);
var arrayOfHeats = model.mtrPackage.Heats();
var addToHeats = () => model.mtrPackage.Heats.push(koHeat);
var duplicate = false;
arrayOfHeats.forEach(function (koHeat, i) {
if (arrayOfHeats[i].MTRID() == koHeat.MTRID() && arrayOfHeats[i].HeatID() == koHeat.HeatID() && arrayOfHeats[i].PartID() == koHeat.PartID()) {
duplicate = true;
}
else
duplicate = false;
})
if (!!model.mtrPackage.PackageID()) {
if (duplicate) {
var c = confirm("Warning: Duplicate MTR located on current package.Proceed ?")
if (c) {
ServiceMethods.addHeatToPackage(model.mtrPackage.PackageID(), heat.HeatID).done(addToHeats);
}
if (!c) {
return;
}
}
}
}
First problem: Your loop compares each object to itself because you re-use the variable name koHeat. I believe you really wanted to refer to the "outer" koHeat.
Second problem: You overwrite the duplicate variable in every loop iteration. This is probably not what you intend. Instead you want to stop the loop as soon as a duplicate is found.
How about something along those lines?
export function addPDFToPackage(heat: MTRHeat): void {
var koHeat: MTRHeatWithInclude = ko.mapping.fromJS(heat);
var packageId = model.mtrPackage.PackageID();
koHeat.Include = ko.observable(true);
function equals(a: MTRHeatWithInclude, b: MTRHeatWithInclude): boolean {
return a.MTRID() == b.MTRID() && a.HeatID() == b.HeatID() && a.PartID() == b.PartID();
}
if ( !!packageId && (
!model.mtrPackage.Heats().some(item => equals(item, koHeat)) ||
confirm("Warning: Duplicate MTR located on current package.Proceed ?")
)
) {
ServiceMethods.addHeatToPackage(packageId, heat.HeatID).done(() => {
model.mtrPackage.Heats.push(koHeat);
});
}
}
The equals() function should ideally be a method of the MTRHeatWithInclude class.
I think you're getting a clash between koHeat defined here:
var koHeat: MTRHeatWithInclude = ko.mapping.fromJS(heat);
koHeat.Include = ko.observable(true);
And the variable defined within the forEach call. It's always returning true as (within the scope of the forEach) arrayOfHeats[i] === koHeat.
Try this:
export function addPDFToPackage(heat: MTRHeat): void {
var koHeat: MTRHeatWithInclude = ko.mapping.fromJS(heat);
koHeat.Include = ko.observable(true);
var arrayOfHeats = model.mtrPackage.Heats();
var addToHeats = () => model.mtrPackage.Heats.push(koHeat);
var duplicate = false;
arrayOfHeats.forEach(function (koHeat2, i) {
if (koHeat2.MTRID() == koHeat.MTRID() &&
koHeat2.HeatID() == koHeat.HeatID() &&
koHeat2.PartID() == koHeat.PartID()) {
duplicate = true;
}
})
if (!!model.mtrPackage.PackageID()) {
if (duplicate) {
var c = confirm("Warning: Duplicate MTR located on current package.Proceed ?")
if (c) {
ServiceMethods.addHeatToPackage(model.mtrPackage.PackageID(), heat.HeatID).done(addToHeats);
} else {
return;
}
}
}
}

Object has-property-deep check in JavaScript

Let's say we have this JavaScript object:
var object = {
innerObject:{
deepObject:{
value:'Here am I'
}
}
};
How can we check if value property exists?
I can see only two ways:
First one:
if(object && object.innerObject && object.innerObject.deepObject && object.innerObject.deepObject.value) {
console.log('We found it!');
}
Second one:
if(object.hasOwnProperty('innerObject') && object.innerObject.hasOwnProperty('deepObject') && object.innerObject.deepObject.hasOwnProperty('value')) {
console.log('We found it too!');
}
But is there a way to do a deep check? Let's say, something like:
object['innerObject.deepObject.value']
or
object.hasOwnProperty('innerObject.deepObject.value')
There isn't a built-in way for this kind of check, but you can implement it easily. Create a function, pass a string representing the property path, split the path by ., and iterate over this path:
Object.prototype.hasOwnNestedProperty = function(propertyPath) {
if (!propertyPath)
return false;
var properties = propertyPath.split('.');
var obj = this;
for (var i = 0; i < properties.length; i++) {
var prop = properties[i];
if (!obj || !obj.hasOwnProperty(prop)) {
return false;
} else {
obj = obj[prop];
}
}
return true;
};
// Usage:
var obj = {
innerObject: {
deepObject: {
value: 'Here am I'
}
}
}
console.log(obj.hasOwnNestedProperty('innerObject.deepObject.value'));
You could make a recursive method to do this.
The method would iterate (recursively) on all 'object' properties of the object you pass in and return true as soon as it finds one that contains the property you pass in. If no object contains such property, it returns false.
var obj = {
innerObject: {
deepObject: {
value: 'Here am I'
}
}
};
function hasOwnDeepProperty(obj, prop) {
if (typeof obj === 'object' && obj !== null) { // only performs property checks on objects (taking care of the corner case for null as well)
if (obj.hasOwnProperty(prop)) { // if this object already contains the property, we are done
return true;
}
for (var p in obj) { // otherwise iterate on all the properties of this object.
if (obj.hasOwnProperty(p) && // and as soon as you find the property you are looking for, return true
hasOwnDeepProperty(obj[p], prop)) {
return true;
}
}
}
return false;
}
console.log(hasOwnDeepProperty(obj, 'value')); // true
console.log(hasOwnDeepProperty(obj, 'another')); // false
Alternative recursive function:
Loops over all object keys. For any key it checks if it is an object, and if so, calls itself recursively.
Otherwise, it returns an array with true, false, false for any key with the name propName.
The .reduce then rolls up the array through an or statement.
function deepCheck(obj,propName) {
if obj.hasOwnProperty(propName) { // Performance improvement (thanks to #nem's solution)
return true;
}
return Object.keys(obj) // Turns keys of object into array of strings
.map(prop => { // Loop over the array
if (typeof obj[prop] == 'object') { // If property is object,
return deepCheck(obj[prop],propName); // call recursively
} else {
return (prop == propName); // Return true or false
}
}) // The result is an array like [false, false, true, false]
.reduce(function(previousValue, currentValue, index, array) {
return previousValue || currentValue;
} // Do an 'or', or comparison of everything in the array.
// It returns true if at least one value is true.
)
}
deepCheck(object,'value'); // === true
PS: nem035's answer showed how it could be more performant: his solution breaks off at the first found 'value.'
My approach would be using try/catch blocks. Because I don't like to pass deep property paths in strings. I'm a lazy guy who likes autocompletion :)
JavaScript objects are evaluated on runtime. So if you return your object statement in a callback function, that statement is not going to be evaluated until callback function is invoked.
So this function just wraps the callback function inside a try catch statement. If it catches the exception returns false.
var obj = {
innerObject: {
deepObject: {
value: 'Here am I'
}
}
};
const validate = (cb) => {
try {
return cb();
} catch (e) {
return false;
}
}
if (validate(() => obj.innerObject.deepObject.value)) {
// Is going to work
}
if (validate(() => obj.x.y.z)) {
// Is not going to work
}
When it comes to performance, it's hard to say which approach is better.
On my tests if the object properties exist and the statement is successful I noticed using try/catch can be 2x 3x times faster than splitting string to keys and checking if keys exist in the object.
But if the property doesn't exist at some point, prototype approach returns the result almost 7x times faster.
See the test yourself: https://jsfiddle.net/yatki/382qoy13/2/
You can also check the library I wrote here: https://github.com/yatki/try-to-validate
I use try-catch:
var object = {
innerObject:{
deepObject:{
value:'Here am I'
}
}
};
var object2 = {
a: 10
}
let exist = false, exist2 = false;
try {
exist = !!object.innerObject.deepObject.value
exist2 = !!object2.innerObject.deepObject.value
}
catch(e) {
}
console.log(exist);
console.log(exist2);
Try this nice and easy solution:
public hasOwnDeepProperty(obj, path)
{
for (var i = 0, path = path.split('.'), len = path.length; i < len; i++)
{
obj = obj[path[i]];
if (!obj) return false;
};
return true;
}
In case you are writing JavaScript for Node.js, then there is an assert module with a 'deepEqual' method:
const assert = require('assert');
assert.deepEqual(testedObject, {
innerObject:{
deepObject:{
value:'Here am I'
}
}
});
I have created a very simple function for this using the recursive and happy flow coding strategy. It is also nice to add it to the Object.prototype (with enumerate:false!!) in order to have it available for all objects.
function objectHasOwnNestedProperty(obj, keys)
{
if (!obj || typeof obj !== 'object')
{
return false;
}
if(typeof keys === 'string')
{
keys = keys.split('.');
}
if(!Array.isArray(keys))
{
return false;
}
if(keys.length == 0)
{
return Object.keys(obj).length > 0;
}
var first_key = keys.shift();
if(!obj.hasOwnProperty(first_key))
{
return false;
}
if(keys.length == 0)
{
return true;
}
return objectHasOwnNestedProperty(obj[first_key],keys);
}
Object.defineProperty(Object.prototype, 'hasOwnNestedProperty',
{
value: function () { return objectHasOwnNestedProperty(this, ...arguments); },
enumerable: false
});

Advantages of treating function as an object

Recently I came across a simple Command pattern implementation in JavaScript that uses function as an object instead of pure object to define functionality:
var CommandManager = (function() {
function CommandManager() {}
CommandManager.executed = [];
CommandManager.unexecuted = [];
CommandManager.execute = function execute(cmd) {
cmd.execute();
CommandManager.executed.push(cmd);
};
CommandManager.undo = function undo() {
var cmd1 = CommandManager.executed.pop();
if (cmd1 !== undefined){
if (cmd1.unexecute !== undefined){
cmd1.unexecute();
}
CommandManager.unexecuted.push(cmd1);
}
};
CommandManager.redo = function redo() {
var cmd2 = CommandManager.unexecuted.pop();
if (cmd2 === undefined){
cmd2 = CommandManager.executed.pop();
CommandManager.executed.push(cmd2);
CommandManager.executed.push(cmd2);
}
if (cmd2 !== undefined){
cmd2.execute();
CommandManager.executed.push(cmd2);
}
};
return CommandManager;
})();
and the usage:
CommandManager.execute({
execute: function(){
// do something
},
unexecute: function(){
// undo something
}
});
//call unexecute of prev. command
CommandManager.undo();
//call execute of prev. command
CommandManager.redo();
My question would be, is there any advantages in defining CommandManager function this way, instead of directly defining properties on object literal and assigning it back to var CommandManager
The only use for that would be that you have a function that does absolutely nothing:
CommandManager(); // does nothing, returns undefined
Other than that, you can just as well write the code as an object literal and use this to avoid it being dependant on its own name:
var CommandManager = {
executed: [],
unexecuted: [],
execute: function execute(cmd) {
cmd.execute();
this.executed.push(cmd);
},
undo: function undo() {
var cmd1 = this.executed.pop();
if (cmd1 !== undefined){
if (cmd1.unexecute !== undefined){
cmd1.unexecute();
}
this.unexecuted.push(cmd1);
}
},
redo: function redo() {
var cmd2 = this.unexecuted.pop();
if (cmd2 === undefined){
cmd2 = this.executed.pop();
this.executed.push(cmd2);
this.executed.push(cmd2);
}
if (cmd2 !== undefined){
cmd2.execute();
this.executed.push(cmd2);
}
}
}

I am looking for a smart way to check the object parameter passed to a function

I am in the following situation:
I have to check if the object parameter passed to a function is valid:
Exmaple:
function (opt) {
if (opt && opt.key && opt.key2) {
// make something
}
}
Is there a better way to make this kind of check?
Not really.
Unless you can use opt.pleaseReadMyMind() ;-)
You could create a method that will check if all fields have values different to null, though.
That's the most compact way of doing it.
The most correct way would be:
if( typeof opt !== "undefined" && typeof opt.key !== "undefined" && typeof opt.key2 !== "undefined") {
But as you can see that's quite a mouthful and not really necessary.
Just write a simple test routine to verify the object given a list of property names:
// usage: testProps(object to test, [list, of, property, names])
// returns true if object contains all properties
function testProps(obj, props)
{
if (obj === null)
return false;
var i;
for (i=0; i<props.length; ++i)
{
if (!(props[i] in obj))
return false;
}
return true;
}
And then in your function:
if (!testProps(obj, ['key', 'key2'])
return;
What you are doing is valid, but it does have flaws.
if (opt && opt.key && opt.key2) {
This check would fail if opt.key has falsely values [0,null,false,and so on]
In that case you would have to do a typeof check to make sure it is not undefined.
if (opt && typeof opt.key !== "undefined" && opt.key2) {
Yeah, but it's only "better" if you have a lot of keys to check, not just three. Something like this:
function opt(opt) {
for(var i = 0; i<3; i++) {
if(typeof opt["key"+((i > 0) ? "" : i + 1))] === "undefined") {
return;
}
}
// create object
}
If opt is undefined all its keys will be too, so there's an implicit check for that as well.
You could also define the variable names you want to check in array, something like this:
var propsToCheck = ["key", "key1", "key2"];
function(opt) {
for(var i = 0, ii = propsToCheck.length; i<ii; i++) {
if(typeof opt[propsToCheck[i]] === "undefined") {
return;
}
// create object
}
}
Not really much of a better solution, but it does allow for less typing if you're planning on checking more than three or four properties.
You could always do it like this:
function validate(o, args) {
if (typeof(o) == 'object' && args instanceof Array) {
for (var i = args.length - 1; i >= 0; --i) {
if (typeof(o[args[i]]) === 'undefined') return false;
}
return true;
} else {
return false;
}
}
function myFunction(obj) {
if (validate(obj, ['foo', 'bar'])) {
// Your code goes here.
} else {
// Object passed to the function did not validate.
}
}
Here's a fiddle for you: http://jsfiddle.net/reL2g/

Categories

Resources