This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How would you overload the [] operator in javascript
Is it possible to overload the [] operator for arrays in Javascript?
For instance I would like to modify the behavior of the bracket so that when it accesses an index out of range it returns 0 instead of undedined.
I know I could probably get away with something like this:
function get(array, i) {
return array[i] || 0;
}
But that's not really modifying the behavior of arrays the way I want.
Since [] is not an operator, you can't "override" it, but you can add property to Array's prototype, which may be helpful in your specific case. Hovewer, it is a bad practice:
Array.prototype.get = function(i, fallback) { return this[i] || fallback; }
a = [1, 2, 3]
a.get(0, 42)
1
a.get(4, 42)
42
[] is not an operator, and you can't override it.
You can override accessors for other javascript objects (that is override ['somespecificvalue'] for writing or reading) but not the [] of arrays.
I'll add I'm glad you can't override it. I don't see the point except in making a whole application unreadable (an application where the basic syntactic elements can't be understood before you've read the whole code to be sure there isn't a change is unreadable).
Related
This question already has answers here:
Why does typeof array with objects return "object" and not "array"? [duplicate]
(3 answers)
Closed 2 years ago.
I'm learning JavaScript, so pardon any mistakes in how I phrase the question.
let nan={
n:3,
j:4
};
let nag = Object.keys(nan)
> nag
(2) ["n", "j"]0: "n"1: "j"length: 2__proto__: Array(0)
> typeof nag
"object"
Why is nag an object and not an array? And that makes difference when you want to access, you will be not able to access with dot notation I think we need in that case square bracket
This is because internally javascript engines store Arrays as objects. Therefore, when you ask for the typeof an array, it returns an object since that is what it is. Essentially, in javascript, Array is an abstraction over native object (an indexed collection object).
If you want to know whether a variable is an Array and not an object you should use Array.isArray(nag). This returns a boolean.
You can lookup the docs here:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray
or if you are in the mood, lookup the typeof spec at:
https://www.ecma-international.org/ecma-262/#sec-typeof-operator
tip: With JS, whenever in doubt, lookup the specs. It's probably the best place to clear up confusions
In Javascript, everything that is not a primitive (numbers, bigints, strings, symbols) are objects. This includes arrays. Objects also have square bracket notation to look up a key, and the dot notation is just a shorthand for looking up a string key:
const a = {
foo: "bar"
};
a.foo // "bar"
a["foo"] // "bar"
This question already has answers here:
Why is it Object.defineProperty() rather than this.defineProperty() (for objects)?
(3 answers)
Why were ES5 Object methods not added to Object.prototype?
(2 answers)
Closed 3 years ago.
I have have seen that three method of array are static methods are static. Array.isArray(), Array.from(), Array.of. I can understand why they are static methods. Because the variable passed to them can also be something other than array. Same is case with Number and String.
But I cannot understand that why almost all the methods of Object are static. Why keys, entries,values etc are not on prototype.
Is there any advantage of putting them as static method?
What problems we would have faced if we had Object.prototype.keys/entries/values...
The problem with Object methods being on the prototype is that objects in general can have arbitrary key-value pairs. For example, if there was such a thing as Object.prototype.values, it could very easily cause confusion when you had an object which you intended to have a values property, eg
const foo = { values: ['val1', 'val2'] };
If Object.prototype.values were a thing, to use it here, you would have to do something like
const fooValues = Object.prototype.values.call(foo);
Better for values to be a static method to avoid such name collisions.
If the properties of your objects could be functions as well, it could be even worse, for example:
const foo = {
info: ['a', 'b', 'c'],
values() {
return this.info;
}
};
Now, if Object.prototype.values was a thing, and you saw foo.values() in the code, what do you think it would mean? Was the programmer intending to call the values property of foo (which is what the code would result in), or was the programmer intending to use Object.prototype.values? It'd be an easy source of bugs and hard-to-read code.
Same thing for the other Object static methods - they could easily result in name collisions.
This question already has answers here:
How variables are allocated memory in Javascript?
(2 answers)
Closed 4 years ago.
I am looking at the spec:
http://www.ecma-international.org/ecma-262/5.1/#sec-11.9.6
http://www.ecma-international.org/ecma-262/5.1/#sec-9.12
I have seen JS code do this:
var a = function(){}
var b = function(){}
var c = a;
console.log(a === b);
console.log(a === c);
the code works as expected, it seems to use strict equality - it doesn't convert the functions to strings and then compare strings - that would be crazy - it uses memory address or something like with Java, right?
How does it actually work? Does anyone know? The spec doesn't seem to mention function comparison, or objects for that matter.
it uses memory address or something like with Java, right?
Pretty much. A variable referencing an object is essentially a reference to a memory location - objects (and functions) are only equal if they reference the same location in memory. Thus, { foo: 'bar' } !== { foo: 'bar' } because each object was created separately.
All non-objects (primitives) can be considered to compare by value, though.
This question already has answers here:
Null-safe property access (and conditional assignment) in ES6/2015
(11 answers)
JS checking deep object property existence [duplicate]
(2 answers)
Closed 6 years ago.
I dont know if a.b is set. I want to do something only if a.b[0].c is true. I can do something like this:
if (a.b && a.b[0] && a.b[0].c) {
// ...
}
Is there a shortcut to check nested existence? Can I simplify this kind of condition?
I used to code golf, and one of the tricks we used is the following.
(myArray || [])[0] || 0
First, myArray || [] is evaluated, if myArray exists, this returns it, if it doesn't, then it returns an empty array. Let's say myArray isn't defined. Next, the [][0] || 0 expression gets evaluated ans because [][0] is undefined, this returns 0.
In your case it could be used the following way:
((a.b || [])[0] || {}).c || {}
This returns an empty object if something's undefined.
I'm not saying you should use this (in fact, you shouldn't), I just want to show you, that there is a smaller solution.
Update:
If tc39 gets through, then you'll have a much better solution using optional chaining:
a.b?[0]?.c
This question already has answers here:
Null-safe property access (and conditional assignment) in ES6/2015
(11 answers)
Closed 6 years ago.
I believe there's a mechanism for this in CoffeeScript (the ? token), but I'm wondering if there's a better way to do this kind of check in ES6:
if (item && item.integrations && item.integrations.slackData) ...
(besides writing a helper function, which is the immediately obvious solution)
EDIT: The goal here is to make the code is simple and terse as possible.
Example object:
item = { integrations: { slackData: { url: '...' } } };
EDIT 2: Thanks for pointing out the duplicates. I couldn't figure out what terms to search for. I'm probably going to go with using lodash's _.get() function.
You can use Array.prototype.every()
var check = [item, item.integrations, item.integrations.slackData]
.every(function(element) { return element });
Edit, Updated
As noted at comments by #FelixKling, the pattern at above using .every() will fail if item.integrations is undefined.
Given the example object at Question you can use JSON.stringify(), String.prototype.match() with RegExp /"integrations":|"slackData":|"url":/g/, then check that .length of resulting array, if any, is equal to the number of properties expected; in the present case 3.
A javascript object which is passed to JSON.stringify() should have properties with the following pattern:
" followed by property followed by " followed by :. Depending on the source object, the RegExp can be further adjusted to meet the specific properties and values of that object.
JSON.stringify(item).match(/"integrations":|"slackData":|"url":/g).length === 3
Note that JSON.stringify() has a replacer option which can be used to match properties of the object. The replacer function option is recursive. See also
remove object from nested array
Nested object and array destructuring
Convert javascript object to array of individual objects
How do I filter Object and get a new Object?
but I'm wondering if there's a better way to do this kind of check in
ES6:
The present Answer does not attempt to indicate that using JSON.stringify() and RegExp to match or filter a javascript object is "better"; but only that the approach can meet the described requirement at the present Question.