I know it has been asked and answered how to set a default parameter for a javascript function by Tilendor
I was wondering if I had a function containing a series of booleans.
For example, a function called 'anAnimal' and as a default I set a value of false to three propertys. fly, swim, and climb.
What would I do if I just want to pass in an argument of true to my property called climb?
Currently when calling in the method I have to pass in a value of false for fly and swim even though I have already predefined them as false.
This is what I am attempting and I would like the result to say true instead of false
function anAnimal (fly = false, swim = false, climb = false) {
this.canFly = fly;
this.canSwim = swim;
this.canClimb = climb;
}
var cat = new anAnimal(true)
var theCat = 'This cat can climb: ' + cat.canClimb;
document.write(theCat);
You can pass an object instead of arguments and populate default option based on inputs.
function anAnimal(obj) {
var defaults = {
fly: false,
swim: false,
climb: false
}
//copy the values of all enumerable own properties from one or more source objects to a target object.
Object.assign(defaults, obj);
//Assign the values
this.canFly = defaults.fly;
this.canSwim = defaults.swim;
this.canClimb = defaults.climb;
}
var cat = new anAnimal({
climb: true
});
var theCat = 'This cat can climb: ' + cat.canClimb;
document.write(theCat);
However I would recommend to use setters i.e. setClimb()
Related
I have a class Action below. Default values for _actionOver and _peopleAffected are defined.
class Action {
constructor(staffName, description, actionOver, peopleAffected){
this._staffName=staffName;
this._description=description;
this._actionOver=false;
this._peopleAffected=0;
}
Now I define a new object of this class and change values for actionOver and _peopleAffected
let a= new Action ('Raul', 'Goal 1: Qaulity Education', true,10);
When I print this in console
console.log(a._actionOver); *// gives false
console.log(a._peopleAffected); *// gives 0*
Should not it give true and 10 as output, if i have changed values in object. If not how do I change default value of an constructor attribute?
You're just ignoring the constructor arguments and always assign the same initial value.
I guess you actually wanted to use default parameter values?
class Action {
constructor(staffName, description, actionOver = false, peopleAffected = 0){
// ^^^^^^^^ ^^^^
this._staffName = staffName;
this._description = description;
this._actionOver = actionOver;
// ^^^^^^^^^^
this._peopleAffected = peopleAffected;
// ^^^^^^^^^^^^^^
}
You're not assigning a default value, you're just assigning a value and ignoring the values passed as arguments.
Once you defined your default:
this._actionOver=false;
You must check if other values have been passed via arguments and overwrite the defaults:
this._actionOver=false;
if (actionOver) this._actionOver = actionOver;
You can do a one liner:
this._actionOver = actionOver || false;
Or just use function parameter defaults:
constructor(staffName, description, actionOver = false, peopleAffected = 0){
// ....
this._actionOver=actionOver;
}
I've finally used another logic (using "let" with break), but I would be happy to have (if it's feasible) another solution:
I've built a validation service which iterate over (injected) list of objects that contains regex expressions and relevant message (and input element) for each expression. I'm using every() method to iterate over the regex expressions. The service knows to return true or false when testing the regex.
The problem is that except for getting true\false I would like the consumer of the service to get the relevant message and the input element. So, in the service class I have 2 properties (lets call them "message" and "element") and I thought to set them accordingly. But, when I'm in the context of the every - the "this" refer to the context and not to the class. I thought of sending those 2 properties as parameters to the every method. Is that the best practice?
See relevant code:
export class userValidation
{
constructor() {
this.validationMessage = '';
this.validationElement = '';
//}
validateByExpression(elementValidator, valueToValidate, functionToExec) {
var validationMessage = this.validationMessage;//Trying to get reference - no go
if (elementValidator.regex.test(valueToValidate) == false)
{
//This is the part where I need to store\return the relevant message
validationMessage = elementValidator.message; // fails
return false;
}
else
{
return true;
}
}
validate(validationElement, elementName, valueToValidate)
{
var regexExpList = new Array(validationElement);
var getValidationMessage = this.getValidationMessage;
var validateByExpression = this.validateByExpression;
var validationMessage = this.validationMessage;
return regexExpList.every(function(regexExp) { return
getValidationMessage(validateByExpression, regexExp[elementName],
valueToValidate, validationMessage) });
}
}
I am trying to make a preset list of options that are allowed in my object list. Here is code
var a = function(cmd, options){
var objList = [options.search ,options.demand];
if(!(options in objList)){
console.warn('Not an Allowed * in the options Property');
}
};
or should I do
var a = function(cmd, options){
var objList = [search , demand];
if(!(options in objList)){
console.warn('Not an Allowed option in the options Property');
}
};
Basically what I want to do is set that search and demand are allowed options in the options Property so later than can do
a('cmd',{
search:'',
demand:function() {
alert('Hello');
},
//warn that the next option is not allowed
quote: function() {
alert('quote of user');
}
});
If you are having trouble understanding what I am asking please ask and I will do my best to explain a bit more.
maybe writing it like so would be better?
var a = function(cmd, options){
options = {
theme: function(color) {
$('body').css('backgroundColor',color);
},
color:''
};
};
a('cmd',{
theme:'#000'//though this is not working?
});
You could check each property in options against an array of allowed options like this:
var a = function(cmd, options){
var allowedOptions = ["search", "demand"];
var hasDisallowedOptions = false;
for (option in options) {
if(allowedOptions.indexOf(option) === -1 ) {
hasDisallowedOptions = true;
break;
}
}
// if hasDisallowedOptions is true, then there is a disallowed option
};
jsfiddle with a couple test cases/examples
A one idea of passing arguments in an object is, that it allows you to choose which argument you want to use in a function, you can simply ignore extra properties in the options object. Hence you don't need to "filter" the properties of the argument either.
Let's assume you've a function like this:
var a = function (cmd, options) {
var theme = {
backgroundColor: options.bgColor,
color: options.color
}
// Do something with theme
// Notice also, that there was no use for options.extra in this function
}
Then you invoke a like this:
a('cmd', {
bgColor: '#ff0',
color: '#000',
extra: 'This is an extra property'
});
Now you can see, extra is not used in a at all, though it was a property of the anonymous object passed to a as an argument. Also all arguments passed to a are garbage collected, unless you're not going to create a closure, i.e. returning a local value or a function from a.
I've been creating some tests for my Dojo widget to check that boolean flags are being set correctly. However, I've found that since I have altered my constructor to pass in an object, previously ran tests seem to affect the subsequent tests.
I've tried destroying the widget in the tear down methods, but whatever I seem to do, the value persists.
Can anyone suggest what I might be doing wrong?
My widget code:
var showControls = true;
return declare([WidgetBase, TemplatedMixin, _WidgetsInTemplateMixin], {
templateString: template,
constructor: function (params) {
this.showControls = (typeof params.showControls === "undefined" || typeof params.showControls != "boolean") ? this.showControls : params.showControls;
}
});
My test class is:
var customWidget;
doh.register("Test controls", [
{
name: "Test controls are not visible when set in constructor",
runTest: function() {
var params = { showControls: false };
customWidget = new CustomWidget(params);
doh.assertFalse(customWidget.getShowControls());
}
},
{
name: "Test controls are visible when set in constructor with string instead of boolean",
runTest: function() {
var params = { showControls: "wrong" };
customWidget= new CustomWidget(params);
doh.assertTrue(customWidget.getShowControls());
}
}
]);
So, the first test passes, as showControls is set to false, however the 2nd test attempts to create a new instance, in which the constructor will check that the value is a boolean. When I debug this however, it thinks showControls starts out as 'false', not true.
Any clues?!
Thanks
dijit/_WidgetBase has a mechanism of mixing in constructor parameters and it is the reason of the behavior you described. One of the possible solutions is to define a custom setter as a method _set[PropertyName]Attr:
var defaults = {
showControls: true
}
var CustomWidget = declare([_WidgetBase, _TemplatedMixin], {
templateString: "<div></div>",
constructor: function(params) {
declare.safeMixin(this, defaults);
},
_setShowControlsAttr: function(value) {
this.showControls = (typeof value === "boolean") ? value : defaults.showControls;
}
});
See it in action: http://jsfiddle.net/phusick/wrBHp/
I would suggest you list any members of your widget, if you do not, things passed into the constructor may not be properly recognised. It seems you want to use this.showControls, so you should have a showControls member. like this :
return declare([WidgetBase, TemplatedMixin, _WidgetsInTemplateMixin], {
templateString: template,
showControls: true, // default value
constructor: function (params) {
// no further action, params are automatically mixed in already
}
});
Be careful when listing members, dojo interprets arrays and objects as class members (like static in Java, AFAIK they're attached to the prototype) so if you want each object to have e.g., a separate array of values, list it as null and initialize in your constructor.
How do you achieve the following thing in Javascript
1) var MyObject={
2) tableView:true,
3) chartView:!(this.tableView)
4) }
The code at line number 3 is not working. Whats wrong in that line ?
What i basically want to do is set "chartView" to opposite of "tableView" whenever tableView is set from code.
Since you're in the process of creating the object, this is not bound to that object. Moreover, since you want chartView to always evaluate to the opposite of tableView, even if the latter changes further down the line, a function would be a better approach:
var MyObject = {
tableView: true,
chartView: function() {
return !this.tableView;
}
};
Now you can do:
var chartView = MyObject.chartView(); // false.
MyObject.tableView = false;
chartView = MyObject.chartView(); // true.
You can't use this to refer to an object in an object literal's properties. You can use this inside a function that is a method of that object:
var MyObject = {
tableView: true,
chartView: function () {
return !this.tableView;
}
}
Based on your requirement, this may be an answer too,
var MyObject = {
view : function(bool){
this.tableView = bool;
this.chartView = !(bool);
}
tableView: true,
chartView: false
}
MyObject.view(false)
console.log(MyObject.tableView); // Outputs false
console.log(MyObject.chartView) // Outputs true
This way you will always have opposite of tableView in chartView with a single function call.