So, i'm trying to make a simple Discord Bot using javascript, and I want to detect if a player username is on the banned list.
I have an array
var banned = ['Andrew','David']
and an if
if (message.author.username instanceof banned) {.....
but when I run it, it outputs
if (message.author.username instanceof banned)
^
TypeError: Right-hand side of 'instanceof' is not callable
What can I do?
This is not what instanceof is for. instanceof is used to see if an object is an instance of a specific constructor (ex: banned instanceof Array).
If you just want to see if an element is in an array, you can use .indexOf().
if(banned.indexOf(message.author.username) != -1)
I was getting the same error on vue / nuxt js.
The problem was setting the prop type wrong:
blog: {
type: {},
required: false,
},
The right way doing it is setting the type Object instead {}
blog: {
type: Object,
required: false,
},
instanceof is used to check if an object is an instance of a class. What you want to do is to check if a string is in an array like this:
if (banned.indexOf(message.author.username) >= 0) {...
instanceof is used to see if an object is of a particular type. You're trying to see if an object is a member of an array.
Try the includes or indexOf methods of the Array object.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/includes
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf
I know I am late here to answer, but I would definitely consider includes() when it comes to code maintainability and first impression of the code.
ES2016 Specifications included the includes() for Array data structure. The includes() check whether an array includes a certain element, returning true or false as appropriate.
But in ES5 we are used to performing operations like this with indexOf() method.
Why use includes?
The includes method finds NaN and undefined whereas the indexOf method doesn't.
Example to find NAN in the array:
const array = [NaN];
if (array.indexOf(NaN) == -1){
console.log("NaN not found in the array");//NaN not found in the array
}
const array1 = [NaN];
if (array1.includes(NaN)){
console.log("true. NAN was found in the array");// true. NAN was found in the array
}
Example to find undefined in the array:
const array = [, , , ,];
if(array.includes(undefined)){
console.log("true array elements are undefined");// true array elements are undefined
}
const array1 = [, , , ,];
if(!array1.indexOf(undefined) == -1 ){
console.log("true. array elements are undefined");
}else {
console.log("Sorry can't find undefined");// Sorry can't find undefined
}
The includes method does not distinguish between -0 and +0(This is not a bug, but clearly how javascript works.
const a = [-0].includes(+0);
console.log(a);//true
In many cases, I have seen indexOf is little faster than include. It depends where you need to compromise. Also, ES6 includes performance is very fast as compared to lodash's includes method.
Performance comparison source.
Related
I learn Javascript and read and understand how the includes works to test if a value exists in an array.
My problem comes when I have an Array of items that look like this this:
state = { focused: null, files: [] };:
The image show this here:
When I add a new newFile and it's the same it should not add it ok but the evaluation,
if (newFile && !files.includes(newFile)) {.. always say false so how to test for this do I have to test on individual values inside newFiles?
Array.includes will not do a deep comparison between object, only a shallow one comparing references. This way even objects that have same values they would fail on test because they have different references.
In your case you could compare id, which should be unique for each object. You can use Array.every that checks if all values pass in the test. This way you want to check that every file id doesn't match newFile id:
if (newFile && files.every(({id}) => newFile.id !== id))
Array.includes does reference comparison for Array or Object, so instead you can use Array.filter
if (newFile && newFile.filter(e => { /*Comparison logic */ }).length > 0)
This is the jquery code i am using
console.log(arrayPgggoData[taxonomy]);
console.log(jQuery.isEmptyObject(arrayPgggoData[taxonomy]));
And I don't know why it is returning true.
Also, what I am actually trying to see if the key inside is not an empty string.
The documentation clearly states:
The argument should always be a plain JavaScript Object as other types of object (DOM elements, primitive strings/numbers, host objects) may not give consistent results across browsers. To determine if an object is a plain JavaScript object, use $.isPlainObject()
But you are checking over an array.
To check if an array has no elements, you can simply rely on its .length property.
arrayPgggoData[taxonomy].length === 0
If you have some array values that you want to consider as "empty" values, then .filter method is your friend.
nonEmptyValues = arrayPgggoData[taxonomy].filter(function(el) { return el !== '' })
ES6 friendly syntax
const nonEmptyValues = arrayPgggoData[taxonomy].filter(el => el !== '')
This question already has answers here:
Why can I access object property with an array?
(2 answers)
Closed 2 years ago.
I ran into a scenario where JavaScript behaves in a way that is somewhat baffling to me.
Let's say we have an object with two keys foo & bar.
a = { foo: 1, bar: 2 }
Then, I have an array of strings, in this case one 'foo'
b = ['foo']
I would expect the following:
a[b] == undefined
a[b[0]] == 1
BUT, this is what happens:
a[b] == 1
a[b[0]] == 1
Why does JavaScript convert ['foo'] -> 'foo' when used as a key?
Does anyone out there know the reason?
How can this be prevented?
let a = { foo: 1, bar: 2 }
let b = ['foo']
console.log(a[b] == 1) // expected a[b] to be undefined
console.log(a[b[0]] == 1) // expected a[b] to be 1
All the object keys are string, so it eventually convert everything you place inside [] (Bracket notation) to string, if it's an expression it evaluates the expression and convert it's value to string and use as key
console.log(['foo'].toString())
Have a look at this example to understand, here [a] eventually converts a toString using a.toString() and then set it as key to b object
let a = { a : 1}
let b = {
[a] : a
}
// object converted to string
console.log(a.toString())
// object built using [] computed property access
console.log(b)
How can i stop this
In practical scenarios you should never do this, but just to illustrate, you can intercept or override the toString method of your object and return value as string with [] around:
let a = { foo: 1, bar: 2 }
let b = ['foo']
b.toString = function() {
let string = this.join(',')
return "[" + string + "]"
}
console.log(b.toString())
console.log(a[b])
When using an array as a key, javascript call the 'toString()' method of that array, and then try to find the stringified version of the array as the key. And if you call ['foo'].toString() you see this method returns "foo".
Why does JavaScript convert ['foo'] -> 'foo' when used as a key?
Does anyone out there know the reason?
Any time there is confusion as to why JavaScript acts in a way which may be unexpected, then looking at the language definition is the surefire way to exactly figure out what happened.
https://www.ecma-international.org/ecma-262/10.0/ is the most current language definition at the time of posting this.
First, you will want to find the area pertaining to Array access. It is in language lingo though.
12.3.2.1 Runtime Semantics: Evaluation
MemberExpression : MemberExpression [ Expression ]
...
3. Let propertyNameReference be the result of evaluating Expression.
4. Let propertyNameValue be ? GetValue(propertyNameReference).
6. Let propertyKey be ? ToPropertyKey(propertyNameValue).
So, what is happening here is you are accessing your array (the MemberExpression) using [] with an Expression.
In order to access with [] the Expression will be evaluated, and then GetValue will be called. Then ToPropertyKey will be called.
propertyNameReference = Evaluate Expression b = b
propertyNameValue = GetValue(propertyNameReference) = ['foo']
propertyKey = ToPropertyKey(propertyNameValue) = 'foo'
ToPropertyKey, in our situation, leads to ToPrimitive and then to ToOrdinaryPrimitive which states that we should call "toString" on the argument (['foo'] in our case).
This is where the implementation comes in to play. On the implementation side,
The Array object overrides the toString method of Object. For Array objects, the toString method joins the array and returns one string containing each array element separated by commas" MDN - Array toString
When there is only one value in the array, the result will simply be that value.
How can this be prevented?
This is the current way it is implemented. In order to change that, you must either change the default implementation, use detection to prevent the call, or use guidance to prevent the call.
Guidance
Document and enforce calling mechanisms in your code. This may not always be possible. It is at the very least reasonable to expect programmers to not call property access with arrays though.
Detection
This will depend on the current environment. With the most recent iteration of JavaScript, you can use type enforcement to ensure that property access is Number or String. Typescript makes this rather easy (here is a good example). It would essentially just require the access to be defined as:
function ArrayAccess(value: string | number) {
and this would prevent anyone from using the array as an accessor value.
Default Implementation
Changing the default implementation is a terrible idea. It will more than likely cause all sorts of breaking changes, and should not be done. However, just for completeness, here is what it would look like. Primarily I am showing this so you can hopefully recognize it if you see it somewhere and then kill it with fire (or check in some code to fix it if there were no spiders near it).
var arrayToString = [].toString;
Array.prototype.toString = function(){
if(this.length === 1) return;
return arrayToString.call(this);
};
Changing the instance implementation is not much of a better idea either. That is covered by #Code Maniac in a separate answer. "In practical scenarios you should never do this" #Code Maniac states, which I also agree with.
When using an array as a key, javascript call the 'toString()' method of that array, and then try to find the stringified version of the array as the key. And if you call ['foo'].toString() you see this method returns "foo".
I'm following this tutorial to "detect" if a unique number is in an array object. This number is a string.
I'm used to detect in Ruby on Rails so I look for the equivalent in React (JavaScript):
ES6:
...
// this will be "data" in "this.props.data"
data = [
{
id: 1,
order_id: "44",
name: "Some order number name",
},
{
id: 2,
order_id: "65",
...,
}
]
// let num = "44"; Just for this example
renderCreditNote(num){
if (num instanceof this.props.data) {
return num.map(function(p){
return p.order_id
});
}
}
render(){
return({this.renderCreditNote().bind(this)})
}
...
In reality, this will look like this: this.renderCreditNote(this.state.num).bind(this)
So if this num is in the Array, display only that array. Am I doing this the right way? The error is:
Uncaught TypeError: Right-hand side of 'instanceof' is not callable
I don't know Ruby, but based on the description of detect it seems you are looking for array.find in JavaScript. .find iterates over an array - if it finds the item you are looking for it returns it and stops iterating, if it does not find anything undefined is returned.
So for example:
renderCreditNote(num){
return this.props.data.find(function(p){
return num === p.order_id;
});
}
Here's a fiddle: https://jsfiddle.net/7ykt9ze3/
Some ES6 prettification:
renderCreditNote(num){
return this.props.data.find(p => num === p.order_id);
}
Be aware that this isn't completely supported in slightly older browsers, I know from experience IE11 doesn't have it. However it is definitely worth the polyfill.
About the blog you linked - without going into prototypical inheritance, instanceof basically returns true/false if the input is of the data structure. In the blog you linked they are detecting whether or not the input is an object or an array - but only so they can take different actions depending on that input. So if it's an object they simply return the field on that object, if it's an array they iterate over the array with .map and return all the names of those objects in that array.
Edit to check render method:
render(){
return(<div>{JSON.stringify(this.renderCreditNote().bind(this))}</div>)
}
You are supposed to pass a function to instance of in the right hand side. Try and do this.props.data.constructor
I've got a simple array cars of Parse models of class Cars
When I do
var uniqCars = _.uniq(cars);
it doesn't work. uniqCars is exact same as cars. The length of cars is 5 and length of uniqCars is 5 (when it should be 2).
However, when I do:
var uniqCars = _.uniq(cars,
function (c) {
return c.id;
});
It works. My question is, why doesn't it work with the former and works with the latter? Why do I have to be so verbose? Is this an issue with Parse or underscore?
why doesn't it work with the former
because, if you don't pass the comparator function, it by default uses === operator to compare the objects. Quoting the _.uniq documentation,
Produces a duplicate-free version of the array, using === to test object equality. ... If you want to compute unique items based on a transformation, pass an iteratee function
When you use === (Strict Equality operator), no two objects will be the same unless they are one and the same object or same sequence of characters forming a string. For example,
console.assert(({} === {}) === false);
var obj = {};
console.assert(obj === obj);
console.assert("ab" === "a" + "b")
console.assert("ab" === 'a' + "b")
So, it is not specific to Parse but it is the expected behaviour in JavaScript.
The comparisons are made using strict equality. Unless there are multiple references to the same object in the array, they are not going to be strictly equal.
Produces a duplicate-free version of the array, using === to test object equality. In particular only the first occurence of each value is kept. If you know in advance that the array is sorted, passing true for isSorted will run a much faster algorithm. If you want to compute unique items based on a transformation, pass an iteratee function.