Number prototype - javascript

Hi everyone i need an help.
I try to modify Number.prototype to add the function sum.
I want to add some numbers to my initial number.
Number.prototype.sum = async (...nums) => {
var x = //What I have to write to have my inizial number here?
for (var i = 0;i<nums.length;i++) {
x=x+nums[i]
}
return x
}
console.log((10).sum(2)) // output: 12
console.log((10).sum(4,6)) // output: 20
(I use visual studio code and the hint after this. is only number)
I tried with:
Number.prototype.valueOf(this)
Number.prototype.valueOf(this.number)
Number.parseInt(this.toString())
Number.parseFloat(this.toString())
Number.parseInt(this.number.toString())
Number.parseFloat(this.number.toString())
this.valueOf()
this.number.valueOf()

You have to use function to access the correct this context (which is the number that the method is called on). Arrow functions inherit their this context from the parent scope (the global object in this case). Also async is not needed since you are not doing anything asynchronous here:
Number.prototype.sum = function (...nums) {
var x = this
for (var i = 0; i < nums.length; i++) {
x = x + nums[i]
}
return x
}
console.log((1).sum(2, 3))
Aside from the fact that augmenting native prototypes is a bad idea, wouldn't you think that a function like this is better suited for the Array prototype?

Related

How to extend Number in TypeScript by adding a function similar to ++

I would like to extend Number with a plusPlus2 function that will increment the number by 2.
The problem is that I don't know how to assign the result back to the number in the extension function. Something like:
Number.prototype.plusPlus2 = function() {
this = this + 2;
}
And the usage would be:
x = 1;
x.plusPlus2(); // expect x to be 3
Primitives (numbers, strings, booleans) are immutable in javascript.
So anytime you change a primitive, you need to assign it to another variable (or even reassign it to itself).
That being said, you cannot do what you propose, you need to return a new value, containing the value you want, let's say:
Number.prototype.plusplus2 = function() {
return this + 2;
}
And then reassign it:
let x = 5;
x = x.plusplus2();
Then, you may be wondering: how x++ works?
And the answer is, x++ is a syntax sugar for x = x + 1, meaning that, in fact, you are not changing x, but instead, adding 1 to x and reassigning it to itself.
You cannot. That has various reasons:
1) this is read only, as you don't expect it to change during the execution of a method.
2) What you access with this is a Number object that wraps the primitive number. It gets thrown away after the call. So even if you could change the internal value property containing the number, the value of x won't change.
Number.prototype.example = function() { this.stuff = "you see" };
let x = 1; // primitive
x.example(); // wrapped object
// wrapped object gets thrown away
console.log(x.stuff); // undefined, another wrapped object
3) Numbers are immutable and primitive. You can write a new number into x, but you can't turn all 1s into 3s.
You could create a new number, but then you have the problem that you have to write that number into x.
Number.prototype.plus2 = function() { return this + 2 };
let x = 1;
x = x.plus2();
Number.prototype.plus2 = function() {
return this + 2
}
let a = 2
console.log(a.plus2())

Cannot set property '0' of undefined in 2d array

I know this has been asked a lot of times, but how do I fix exactly this thing?
I have a map[][] array (contains tile ids for a game) and I need to copy it to pathmap[][] array (contains just 0's and 1's, it is a path map), however when I do so..
function updatepathmap(){
pathmap = [];
var upm_x = 0;
while (upm_x < map.length){
var upm_y = 0;
while (upm_y < map[upm_x].length){
pathmap[][]
if (canPassthrough(map[upm_x][upm_y])) {
pathmap[upm_x][upm_y] = 1;
} else {
console.log(upm_x);
console.log(upm_y);
pathmap[upm_x][upm_y] = 0;
}
upm_y++;
}
upm_x++;
}
console.log(map);
console.log(pathmap);
}
..it gives me Cannot set property '0' of undefined typeerror at line pathmap[upm_x][upm_y] = 0;
Despite the foo[0][0] syntactic sugar, multi-dimensional arrays do not really exist. You merely have arrays inside other arrays. One consequence is that you cannot build the array in the same expression:
> var foo = [];
undefined
> foo[0][0] = true;
TypeError: Cannot set property '0' of undefined
You need to create parent array first:
> var foo = [];
undefined
> foo[0] = [];
[]
> foo[0][0] = true;
true
You can determine whether it exists with the usual techniques, e.g.:
> var foo = [];
undefined
> typeof foo[0]==="undefined"
true
> foo[0] = true;
true
> typeof foo[0]==="undefined"
false
I would have thought pathmap[][] was a syntax error, I'm surprised you're not seeing one.
Before you can use an array at pathmap[upm_x], you must create an array at pathmap[upm_x]:
pathmap[upm_x] = [];
This would be the first line in your outer while, so:
while (upm_x < map.length){
pathmap[upm_x] = [];
// ...
Remember that JavaScript doesn't have 2D arrays. It has arrays of arrays. pathmap = [] creates the outer array, but doesn't do anything to create arrays inside it.
Side note:
var upm_x = 0;
while (upm_x < map.length){
// ...
upm_x++;
}
is an error-prone way to write:
for (var upm_x = 0; upm_x < map.length; upm_x++){
// ...
}
If you use while, and you have any reason to use continue or you have multiple if branches, it's really easy to forget to update your looping variable. Since looping on a control variable is what for is for, it's best to use the right construct for the job.
Side note 2:
Your code is falling prey to The Horror of Implicit Globals because you don't declare pathmap. Maybe you're doing that on purpose, but I wouldn't recommend it. Declare your variable, and if you need it outside your function, have your function return it.
Side note 3:
map would make this code a lot simpler:
function updatepathmap(){
var pathmap = map.map(function(outerEntry) {
return outerEntry.map(function(innerEntry) {
return canPassthrough(innerEntry) ? 1 : 0;
});
});
console.log(map);
console.log(pathmap);
}

Javascript syntax with functions

I'm not sure what this means or how to word the question correctly.
In the first example I could put the variable before the function "numbers1.forEach(...)" but in the second example I could not "num.square()"?
function forEach(array, action) {
for (var i = 0; i < array.length; i++)
action(array[i]);
}
var numbers2 = [1, 2, 3, 4, 5], sum = 0;
forEach(numbers2, function(number) {
sum += number;
});
console.log(sum);
// → 15
var numbers1 = [1, 2, 3, 4, 5], sum = 0;
numbers1.forEach(function(number) {
sum += number;
});
console.log(sum);
// → 15
// this works!
But this does not work
var square = function(x) {
return x * x;
};
var num = 12;
console.log(square(num));
// → 144
console.log(num.square());
// → TypeError: undefined is not a function (line 9)
// does not work?
Thanks!
Syntax-wise, there's no "magic" happening here. You're describing two very different things.
In your first example, you're passing an Array to your own defined forEach method. In the second example, the forEach you're calling is actually a built-in method on Arrays (see MDN). If you changed your forEach to not invoke action, you'll see that yours breaks and the second one still works.
You can achieve this functionality yourself. You could add a function to Number to make your second example work (although this is not a recommended practice, as it could collide with future JavaScript features [and many other reasons] or break existing functionality):
Number.prototype.square = function() {
return this * this;
};
var num = 12;
var squared = num.square();
alert(squared);
If you remove the forEach function from your first example, it will still work, that is because the Array type has a builtin forEach function.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach
Alternatively try to change your forEach function to each and you will see that it will no longer work.
What you are trying to do is add a new method to an existing type. This is not good practice in JavaScript.
The example with the array works because Array in JavaScript (ECMAScript5) defines a forEach function.
The example with the number doesn't work because Number doesn't define a square function. You can extend Number to include the square function like this:
Number.prototype.square = function(x) {
return this * this;
};

Object.create to create an object with costructor

I am learning Javascript and I am a C++ programmer. I have tried creating an object with a constructor with object.create and here is the result:
var PlayGround ={
initGrid : function(N) {
this.N=N;
this.grid = new Array(N);
for (var i = 0; i < N; i++) {
this.grid[i] = new Array(N);
for (var j = 0; j < N; j++) {
this.grid[i][j] = false;
}
}
return true;
}
};
var PlayGround_property = {
N:{
value: 100,
writable:true
},
grid:{
value:null,
writable:true
}
}
var board= Object.create(PlayGround, PlayGround_property);
It works as I want: the object board contains the object grid, and now I can use the set and get keyword to define the behaviour of the = and () operator.
Anyway I have read around the web that the
this
keyword in Javascript is not safe and I want to be sure that it is referring always to the board object and not to the global window object. Is there a way or I am overthinking?
Other question, are there other ways to write object with a constructor (and maybe other members) in Javascript?
I want to be sure that [this] is referring always to the board object
A function's this is set either by how you call the function, or bind. So just make sure you call methods the right way. If you always call functions as methods of board, then this within the methods will always reference board.
If you are only going to have one instance of board, there doesn't seem much point in using a constructor. If you have multiple instances of board, then you want this to reference the particular instance that called the method so you don't want to fix this using bind.
Crockford just doesn't like the use of new, so encouraged Object.create, it fits his idea of how inheritance should work.
Your pattern could be rewritten to use a constructor something like:
function PlayGround (N) {
this.N = N;
this.grid = []; // Use array literal, it's less to type
for (var i = 0; i < N; i++) {
this.grid[i] = [];
for (var j = 0; j < N; j++) {
this.grid[i][j] = false; // Not sure why you bother with this
}
}
}
var board = new Playground(100);
I'm not exactly sure what you're doing, but that should be close. Note that javascipt is loosely typed, so only initialise variables and properties if you have something useful to assign. Variables are created with a value of undefined, Array properties are only created if you actually assign something to them, creating an array with length N does not create any indexes, e.g.
var arr = new Array(10);
console.log(arr.length); // 10
console.log(arr.hasOwnProperty(0)); // false

JavaScript setting variables?

Can someone explain the second line of this function? is it setting two variables to = 0 at one time? i.e. var i = 0 and var res = 0? If so, is it necessary to set var i = 0 considering that it does that in for(i = 0 ... etc
function sumOnSteroids () {
var i, res = 0;
var number_of_params = arguments.length;
for (i = o; i < number_of_params; i++) {
res += arguments[i];
}
return res;
}
No, the value of i will be undefined, the initializer only applies to "res" in that case. To assign the value you'd need:
var i = 0,
res = 0;
It is setting two variables at once with the var keyword being applied to both, scoping them. Without the var, they would be properties of window (essentially globals).
The first one (i) would be undefined and the second one (res) would be 0.
This is a powerful pattern because...
var should be implicit, but it is not, so we only have to repeat it once.
Less typing for you.
Better for minifying (smaller file size).

Categories

Resources