Why Does [5,6,8,7][1,2] = 8 in JavaScript

Why does [5,6,8,7][1,2] = 8 in JavaScript?

[1,2,3,4,5,6][1,2,3];
^ ^
| |
array + — array subscript access operation,
where index is `1,2,3`,
which is an expression that evaluates to `3`.

The second [...] cannot be an array, so it’s an array subscript operation. And the contents of a subscript operation are not a delimited list of operands, but a single expression.

Read more about the comma operator here.

Why console.log([1, 2, 3, 4, 5, 6, 7, 8, 9, 10][1, 2, 3, 4, 5, 6, 7][1, 2, 3]) logs undefined?

You are on the right track. The second and third group of [...] are a property access with bracket notation, and the 1, 2, 3 are treated as comma operators, evaluating to the last entry in the list. So your code is basically the same as:

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10][7][3]

Now the seventh number in the array is 8:

 8[3]

and that does not have a "3" property.

Why reading an array with more than index doesn't throw an error?

The comma operator evaluates each of its operands (from left to right) and returns the value of the last operand. That's why you get 1.

Does JavaScript have a method like range() to generate a range within the supplied bounds?

It works for characters and numbers, going forwards or backwards with an optional step.

var range = function(start, end, step) {
var range = [];
var typeofStart = typeof start;
var typeofEnd = typeof end;

if (step === 0) {
throw TypeError("Step cannot be zero.");
}

if (typeofStart == "undefined" || typeofEnd == "undefined") {
throw TypeError("Must pass start and end arguments.");
} else if (typeofStart != typeofEnd) {
throw TypeError("Start and end arguments must be of same type.");
}

typeof step == "undefined" && (step = 1);

if (end < start) {
step = -step;
}

if (typeofStart == "number") {

while (step > 0 ? end >= start : end <= start) {
range.push(start);
start += step;
}

} else if (typeofStart == "string") {

if (start.length != 1 || end.length != 1) {
throw TypeError("Only strings with one character are supported.");
}

start = start.charCodeAt(0);
end = end.charCodeAt(0);

while (step > 0 ? end >= start : end <= start) {
range.push(String.fromCharCode(start));
start += step;
}

} else {
throw TypeError("Only string and number types are supported");
}

return range;

}

jsFiddle.

If augmenting native types is your thing, then assign it to Array.range.

var range = function(start, end, step) {    var range = [];    var typeofStart = typeof start;    var typeofEnd = typeof end;
if (step === 0) { throw TypeError("Step cannot be zero."); }
if (typeofStart == "undefined" || typeofEnd == "undefined") { throw TypeError("Must pass start and end arguments."); } else if (typeofStart != typeofEnd) { throw TypeError("Start and end arguments must be of same type."); }
typeof step == "undefined" && (step = 1);
if (end < start) { step = -step; }
if (typeofStart == "number") {
while (step > 0 ? end >= start : end <= start) { range.push(start); start += step; }
} else if (typeofStart == "string") {
if (start.length != 1 || end.length != 1) { throw TypeError("Only strings with one character are supported."); }
start = start.charCodeAt(0); end = end.charCodeAt(0);
while (step > 0 ? end >= start : end <= start) { range.push(String.fromCharCode(start)); start += step; }
} else { throw TypeError("Only string and number types are supported"); }
return range;
}
console.log(range("A", "Z", 1));console.log(range("Z", "A", 1));console.log(range("A", "Z", 3));

console.log(range(0, 25, 1));
console.log(range(0, 25, 5));console.log(range(20, 5, 5));

What is this bracket sequence syntax called in JS?

It's just the comma operator: it evaluates each of its operands (from left to right) and returns the value of the last operand.

Overriding class access by []

...how can I define access to it by brackets

You can't, in the way you've shown. JavaScript doesn't have a syntax for that; instead, it has the comma operator, which doesn't do what you want. Both 0, 1 and 1, 1 evaluate to 1 because the comma operator takes two operands, evaluates the left-hand operand, throws that value away, then evaluates the right-hand operand and takes that result as the comma operator result. So matrix[0, 1] is matrix[1].

Instead, define a method accepting two parameters, and call it (matrix.at(0, 1)), or use an array of arrays and do matrix[0][1].

You could accept a string, matrix["0,1"], by using a Proxy object and then parsing the string in the get and set traps, but I suspect that's not suitable to your use case (or most others).


You've said the width and height of the matrix are set in the constructor. You could store your fields in arrays (perhaps an array of typed arrays, depending on what you're storing in the matrix) and define properties for 0 through height - 1 that get the array for that row. So matrix[0] would be the first row of the matrix as an array / typed array, so matrix[0][0] would be the first cell of the first row. Here's a really basic example:

class Matrix {
constructor(height, width) {
this.data = Array.from(
{length: height},
() => Array.from({length: width}).fill(0)
);
for (let y = 0; y < height; ++y) {
Object.defineProperty(this, y, {
value: this.data[y]
});
}
}
toString() {
return this.data.map(row => row.join(",")).join("\n");
}
}

const m = new Matrix(5, 5);
m[1][2] = 1;
console.log(m.toString());

Why does [1,2,3,4][1,2] =3 in JavaScript?

In the expression:

console.log([1,2,3,4][1,2]);

the comma in the second set of square brackets is acting as the comma operator.

As seen in the MDN docs, the comma operator evaluates each side of the comma and returns the final value.

In this case, we get:

console.log([1,2,3,4][2]);

Which returns the third value, that being the one at array subscript 2.



Related Topics



Leave a reply



Submit