I trying a creation of insulted index in Javascript. That´s my code.
var map = [];
function createIndexIfNotExists (posx,posy){
if(typeof(map[posx]===undefined)){
map[posx] = {};
console.log("created: map["+posx+"] typeof="+typeof(map[posx])); //typeof object
}
if(typeof(map[posx][posy]===undefined)){
map[posx][posy] = [];
console.log("created: map["+posx+"]["+posy+"]
typeof="+typeof(map[posx])); //typeof object
}
map[posx][posy].push( {'posx':posx, 'posy':posy }); }
createIndexIfNotExists(10,5);
createIndexIfNotExists(10,6);
But the result is this.
created: map[10] typeof=object
created: map[10][5] typeof=object
created: map[10] typeof=object
created: map[10][6] typeof=object
Why create map[10] two times if typeof is object and not undefined?
On this line you need to move the ()
if(typeof(map[posx]===undefined)){
should be:
if(typeof(map[posx])===undefined){
The same is true for this line:
if(typeof(map[posx][posy])===undefined){
You're finding the type of the comparison which will always evaluate to the string 'boolean' which will evaluate to true.
typeof return the tyoe as a string, so the type checking will be like
if(typeof(map[posx])==="undefined")
and
if(typeof(map[posx][posy])==="undefined")
and also the ( and ) is not required in typeof to wrap the item you are going to check, its a keyword, nit a function. when you are wrapping an expression (map[posx]===undefined in your case) wit () in typeof that meant the preference of executing that expression is higher, and type will be checked upon that result. so the expression resolved map[posx]===undefined resolved first and you are checking the type of the resule true or false
Related
Today as I read the PrimeNg's source code, noticed one thing. The author of one utils class (ObjectUtils) in some cases initialized the arrays, but in other ones not.
Example 1 from source code:
public static generateSelectItems(val: any[], field: string): SelectItem[] {
let selectItems: SelectItem[];
if(val && val.length) {
selectItems = [];
for(let item of val) {
selectItems.push({label: this.resolveFieldData(item, field), value: item});
}
}
return selectItems;
}
Example 2 from source code:
public static filter(value: any[], fields: any[], filterValue: string) {
let filteredItems: any[] = [];
let filterText = this.removeAccents(filterValue).toLowerCase();
if(value) {
for(let item of value) {
for(let field of fields) {
let fieldValue = this.removeAccents(String(this.resolveFieldData(item, field))).toLowerCase();
if(fieldValue.indexOf(filterText) > -1) {
filteredItems.push(item);
break;
}
}
}
}
return filteredItems;
}
In second example he initialized the array filteredItems, but in first one does not (selectItems array). I'm wondering why he did so and if there is any best practices regarding this.
This line:
let selectItems: SelectItem[];
declares a variable, but does not create an array. (It doesn't initialize the variable with anything.) Later, the array is created using [], here:
selectItems = [];
// -----------^^
...and then assigned to the variable.
This line:
let filteredItems: any[] = [];
...combines those two steps by providing a variable initializer.
The key thing to understand is that selectItems in the first example doesn't contain anything, at all, until it has something assigned to it. So it isn't that the programmer "hasn't initialized the array," it's that he/she hasn't initialized the variable.
You don't have to initialize a variable when declaring it. Both let and var declarations without an initializer initialize the variable to undefined (at different times, but that's not important here). (You do need to initialize a constant declared with const when declaring it, since you can't assign to it afterward.)
In a comment you asked:
But when this if(val && val.length) fails in first example, then the function will return undefined. Won't be better if it returns let say an empty array?
That depends purely on what the programmer wants to have happen when val is falsy or has a falsy length. I'm sure there are use cases for returning undefined and for returning an empty array.
You may be wondering, though, about returning undefined when the type annotation on the function says it returns SelectItem[]. Remember that by default, null and undefined are effectively members of every type. You can turn that off with the strictNullChecks option, which is documented as:
In strict null checking mode, the null and undefined values are not in the domain of every type and are only assignable to themselves and any (the one exception being that undefined is also assignable to void).
strictNullChecks would indeed have made that function an error. Compare this code:
function foo(bar: boolean) : Date {
let x : Date;
if (bar) {
x = new Date();
}
return x;
}
foo(Math.random() < 0.5);
Try it in the playground using the Options button to enable/disable
strictNullChecks: TypeScript flags an error when it's enabled.
I have an application that can turns a tex file into a JavaScript object, with key-value pairs. The key being the word and the value being the number of times it has appeared in the text file. Let's go through it together:
FormatText.prototype.toDowncase = function() {
return this._data = this._data.toLowerCase();
};
This turns the words to lowercase
FormatText.prototype.deleteWords = function() {
return this._data = this._data.replace(/\W/g, " ");
};
This replaces all non-words with a space
FormatText.prototype.splitWords = function() {
return this._data = this._data.split(/\s+/);
};
This turns the string in an array and splits at each delimiter
FormatText.prototype.filterEntries = function() {
return this._data = this._data.filter(v => !!v);
};
This one above I have no clue what it does.
FormatText.prototype.countWords = function() {
return this._data = this._data.reduce((dict, v) => {dict[v] = v in dict ? dict[v] + 1 : 1; return dict}, {});
}
Could someone explain this one, however I will get it a try:
This one takes the array and passed the method 'reduce' with two arguments. It counts how many times each individual word has appeared and returns an object with the 'key-value' pairs described at the beginning of this question.
v => !!v means take v, and coerce it to a Boolean type by applying NOT twice. So the filter function is basically removing any falsey values (0, null, undefined) from this._data.
countWords is counting the number of times each word occurs in this._data - it is going through the array and adding 1 to the count if the word has been encountered before, or returning 1 if the word has not been encountered before. It returns an object with the words as keys and the counts as values.
As a note, these functions change the type of this._data, from a string, to an array, to an object. That may cause bugs to appear if e.g. you run the same method twice
Why not just return the value, without NOT NOT, like
v => v
because for filtering the value coerces to a boolean value.
From Array#filter:
Description
filter() calls a provided callback function once for each element in an array, and constructs a new array of all the values for which callback returns a value that coerces to true. callback is invoked only for indexes of the array which have assigned values; it is not invoked for indexes which have been deleted or which have never been assigned values. Array elements which do not pass the callback test are simply skipped, and are not included in the new array.
In this case the double exclamation mark is useless: the value returned from the callback in filter(callback) is then coerced to a boolean automatically, so no need to do it using double exclamation mark. The following lines are equivalent:
.filter(v => !!v)
.filter(v => v)
.filter(Boolean)
This one above I have no clue what it does.
The javascript operator ! (logical not) performs a type coercion (to boolean) on its argument. So applied twice you somehow convert any type to a boolean value which gives you whether it is falsy or truthy.
This is interesting when you want to apply a condition to different types whose semantic is more or less "no value". For example:
!!('') //false
!!(0) //false
!!null //false
!!undefined //false
Could someone explain this one, however I will get it a try
reduce is method of the array prototype which allows to iterate over a collection while aggregating value.
In your specific example the aggregator is a dictionary which maps a word to a count (number of appearance). So if the word is not present in the dictionary it creates a key for this word with a counter initialized to 1 otherwise it increments the counter (if word already present).
A equivalent could be
const countWords = function (words = [], dictionary = {}) {
if(words.length === 0) {
return dictionary;
}
const word = words.pop(); //remove and read the word at the end of the array
if(word in dictionary) {//if key is present in the dictionary
dictionary[word] += 1; // increment
else {
dictionary[word] = 1; // start a counter for new keyword
}
return countWords(words, dictionary);
}
In my project I often find myself checking if a value is an array.
If the value is not an array I create a single element array from it.
If the value is undefined or null, I create an empty array.
The value itself is usually either an array of objects or a single object or undefined
const array = value ? (Array.isArray(value) ? value: [value]) : [];
Is there a more succinct way of doing this (perhaps with lodash or underscore), before I decide to factor this into a separate util function?
You could do
var eventsArray = events ? [].concat(events) : [];
The .concat() function accepts both arrays and individual arguments, so either way you end up with what you want.
since you are using const in your code I assume you are using ES2015 / ES6. ES1015's
Default function parameters allow formal parameters to be initialized with default values if no value or undefined is passed.
function abc(value = []) {
const array = Array.isArray(value) ? value: [value];
}
If you use ES6, you can do the following, it's cleaner than .concat();
function method(value = []) {
const array = [...value];
}
Here's a solution using lodash's castArray and isNil all wrapped up in a mixin:
_.mixin( {'asArray' : function(value){
return _.isNil(value) ? [] : _.castArray(value);
}});
Usage:
_.asArray(null) -> []
_.asArray(undefined) -> []
_.asArray(0) -> [0]
_.asArray(false) -> [false]
_.asArray([1,2,3]) -> [1,2,3]
_.asArray('wibble') -> ['wibble']
A condensed ES2020 way to ensure a variable is an array:
value = [].concat(value ?? [])
Explanation
As #VoteyDisciple explained, the concat function will concatenate single values or an arrays of values. The nullish coalescing operator (??) will use the value on the right (the second empty array) if the value on the left is null or undefined. So if value is null, it will concatenate an empty array to an empty array, which returns an empty array.
Examples
// Different inputs and outputs
values = [].concat([1,2,3] ?? []) // [1,2,3]
values = [].concat(1 ?? []) // [1]
values = [].concat(null ?? []) // []
// Wrap it in a function if you like
function array(value) {
return [].concat(value ?? [])
}
// Use it like this
values = array(values)
// Or even like this
for (let value of array(values)) {
console.log(value)
}
Even shorter solution using .flat()
There is an even slicker way to do it if you don't have to check for the undefined or null value. This basically converts the value to a singleton array if it was not an array before.
[value].flat()
Example usage
[12].flat() // Output: [12]
[[[12]]].flat() // Output: [[12]]
Removing nullish values
If you want to remove nullish values - just add a filter on top of that. This will remove all the values that are falsy.
[value].filter(x => x).flat()
Pitfalls
Due to the fact that 0 (and false) is a falsy value, if you are storing numbers in an array it is advised to explicitly compare array values with null or undefined.
[value].filter(x => x !== null && x !== undefined).flat()
In order to shorten it a bit we could use Lodash's isNil method.
[value].filter(_.isNil).flat()
Recently I've learned that you can use the Boolean keyword to check whether a boolean value is false, e.g. this, where the arrayOfSheeps is simply an array of boolean values.
function countSheeps(arrayOfSheeps) {
return arrayOfSheeps.filter(Boolean).length;
}
As I've been unable to find anything about using 'Boolean' as a keyword, I was wondering if there are any other uses for the word, or even just any resources I can use to learn about it.
Boolean is not a keyword, it is a function, and functions are just objects, that you can pass around. It is the same as:
return arrayOfSheeps.filter(function(x){return Boolean(x)}).length;
Since function(x){return f(x)} === f then you can simplify:
return arrayOfSheeps.filter(Boolean).length;
Based on MDN Boolean,
Do not use a Boolean object to convert a non-boolean value to a
boolean value. To perform this task, instead, use Boolean as a
function
var x = Boolean(expression); // use this...
var x = !!(expression); // ...or this
var x = new Boolean(expression); // don't use this!
So the code is same as:
const b = v => !!v;
arrayOfSheeps.filter(b).length;
arrayOfSheeps.filter(v => !!v).length; // or inline
a pretty simple question, is there ever a case where using a primitive data-type is preferable in javascript, i am specifically bothered by primitive booleans, consider the following code
var bool = new Boolean(false);
if (bool){
alert(bool);
}
it will alert but you will get false, which is kinda confusing (false != falsy).
so is there ever a point in using primitive data-types and especially primitive booleans?
These are not primitives. Primitives are like 100, "foobar", false:
> typeof false
"boolean"
> typeof new Boolean(false)
"object"
new Boolean (or Number or String) is an object and follows objects', not primitives' rules for comparison, boolean conversion etc. These objects are indeed hardly useful for a JS programmer (as opposed to a JS engine which uses them internally).
Note that while it's rarely needed to use Boolean and friends to construct objects (as in x = new Boolean(...)), these functions are sometimes useful per se. For example, the following nice idiom removes all falsy values from an array:
ary = ary.filter(Boolean)
The primitive values are very useful (ex of primitive values: true, false, null, 1, 2, etc). What you are talking about in the question are the Object wrappers around them.
Object wrappers are useful because it allows you to add functions to be called on them. One more important thing is that when you call methods on the primitive values, Object wrappers are created over them and the methods are called on the Object wrappers*.
Example 1: String
String.prototype.sayHello = function() {
return this + ' says hello';
};
// calling a method on a string literal temporarily converts it to a String
console.log('John'.sayHello()); // 'John says hello'
Example 2: Boolean
var bool = new Boolean(false);
console.log(bool); // Boolean
console.log(bool.toString()); // 'false'
console.log(bool.valueOf()); // false
// How you can use it:
Boolean.prototype.toCaps = function() {
return this.valueOf().toString().toUpperCase();
};
console.log(bool.toCaps()); // 'FALSE'
// calling a method on a boolean literal temporarily converts it to a Boolean
console.log(true.toCaps()); // 'TRUE'
console.log((1 === 1).toCaps()); // 'TRUE'
DEMO: http://jsbin.com/apeGOve/1/edit
*) Different Object wrappers are created each time a method is called on a primitive value:
String.prototype.getWrapper = function() { return this; };
String.prototype.setTest = function() { this.test = 'test' };
String.prototype.getTest = function() { return this.test; };
var str = '123';
console.log('Different wrappers each time',str.getWrapper() === str.getWrapper());
var wrapper = str.getWrapper();
wrapper.setTest();
console.log(wrapper.getTest());
console.log(str.getTest());
Your example:
var bool = new Boolean(false);
if (bool){
alert(bool);
}
and you're wanting to know why it alerts false.
bool is the variable, you assigned it a value when you created it. So, when you say if(bool) JavaScript does some coercion and tests whether bool is falsy, it isn't, so the conditional block executes. Now you're at alert(bool) which will try to call the toString method of your object and display the result. The toString method of the boolean object returns the value of the boolean object as a string so, you get the word "false" alerted.
Go ahead, try
var bool = new Boolean(false);
bool.toString = function () {
return 'I need a banana';
}
if (bool){
alert(bool);
}
and you'll get completely different results.
This brings us to your other question of "why" you'd even use the boolean constructor: you can assign properties to the boolean object, you can not assign properties to true and false. You may want to inherit from the boolean object when building some logic handling library with chainable methods, for instance.