Change Behavior of Operators [duplicate] - javascript

This question already has answers here:
Javascript: operator overloading
(9 answers)
Closed 5 years ago.
This is more of a "for fun" sort of thing, as it would be impractical to actually use this. I just want to satisfy my curiosity as to whether or not it's even possible.
I have a function...
function longAdd(a,b){
//computation here
return sum;
}
...which "adds" the values of a and b together as a string; meaning, it iterates through each character and adds them up. Thus, it can compute numbers which are greater than what could otherwise be achieved.
(for the purposes of this question, the actual code should not be relevant, so it is not included)
My question is: would it be possible to directly change the "+" operator to use this function? For instance,
c+d
anywhere in the code would essentially compute longAdd(c,d).
Any possible hacky ways to achieve this? For that matter, can the behavior of any operators be directly changed?
Note: Yes, I am aware this would screw up concatenation and big, numerical values would have to stay strings. This is just a concept I'm curious about.

My question is: would it be possible to directly change the "+" operator to use this function?
No, JavaScript has no user-defined operator overloading at all.
The nearest I can see getting is defining an object with its own valueOf method which returns the result of converting itself to a string and doing your longAdd just on itself, and returning that result. Then the existing + would trigger that behavior on the objects referenced by a and b.
That's not overloading +, just taking advantage of the behavior it already has:
function Thing(val) {
this.val = val;
}
Thing.prototype.valueOf = function() {
// Here I'm just doubling it; you'd actually do your longAdd thing
return this.val * 2;
};
var a = new Thing(1);
var b = new Thing(2);
console.log(a + b); // 6 (1 * 2 + 2 * 2)
Or with ES2015's class:
class Thing {
constructor(val) {
this.val = val;
}
valueOf() {
return this.val * 2;
}
}
const a = new Thing(1);
const b = new Thing(2);
console.log(a + b); // 6 (1 * 2 + 2 * 2)
Or just with objects, no constructors:
var thingPrototype = {
valueOf: function() {
return this.val * 2;
}
};
var a = Object.create(thingPrototype);
a.val = 1;
var b = Object.create(thingPrototype);
b.val = 2;
console.log(a + b); // 6 (1 * 2 + 2 * 2)

Related

Math.floor(Math.random() * 2) always returning the same value in a for loop [duplicate]

This question already has answers here:
Modifying a copy of a JavaScript object is causing the original object to change
(13 answers)
Closed 6 months ago.
var arr = []
var obj = {
a: undefined,
b: undefined,
c: undefined
}
var a = 0
while (a !== 100) {
arr.push(obj)
a++
}
var randNum
for (var i = 0; i < arr.length; i++) {
randNum = Math.floor(Math.random() * 2)
console.log(Math.floor(Math.random() * 2))
arr[i].a = Math.floor(Math.random() * 2)
arr[i].b = 5
}
console.log(arr)
When I console log arr, arr[n].a always equals one number, but thats not what I want, I want it to output a random number, like 0 or 1.
The issue is as VLAZ mentioned in their comment. To fully explore this, we need to understand reference vs. value types in JS.
Let's look at a simple program:
let a = 1;
let b = a;
a = 2;
console.log(b) // prints 1
This works because we're storing a simple, primitive type like a number. With more complex types like arrays and objects, we'll see different behavior.
let a = { foo: true, bar: true };
let b = a;
a.foo = false;
console.log(b) // prints { foo: false, bar: true }
This is because more complex types in JS like arrays and objects are passed by reference, not by value. In essence, this means that when we store an object using a variable, the variable is not storing the values, but rather a reference to the object's location in your machine's memory. Let's add comments to the above code for clarity.
// a stores a pointer to memory location A, where our object literal lives
let a = { foo: true, bar: true };
// b stores a pointer to memory location A
let b = a;
// change a value on the object in memory location A
a.foo = false;
// print the value in memory location A
console.log(b)
This reference vs value differentiation has to do with the complexities of managing memory when we have potentially large, dynamic objects, so JS does a bunch of low-level stuff for us behind the scenes and gives us a nice user-friendly syntax for instantiating a data type that would be more complicated to implement manually in a lower-level language. However, we still have to be aware of this difference.
The crux of your issue is that in each index of your array, you're storing a reference to the exact same object, so when you update one index, you're actually updating the value at the memory location the index is pointing to. Since all the indices are pointing to the same memory location, changing one behaves similarly to changing them all.
Fortunately, armed with this information we can simply devise a way to create a new object on each iteration, whether by copying the reference object or just passing an object literal to the Array.push() method. Here's a potential solution.
let arr = [];
for (let i = 0; i < 100; i++) {
// this "object literal" is defined when push is called, creating a new object on each iteration
arr.push({
a: Math.floor(Math.random() * 2),
b: 5,
c: undefined
});
}

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())

How to multiply objects by specified rules? [duplicate]

This question already has answers here:
Javascript: operator overloading
(9 answers)
Closed 4 years ago.
Let's say i want an object that when multiplied with, it multiplies by two and subtracts 1.
The syntax would look like this:
var a = {
on_multiply: function(context){
return context*2-1
}
};
alert(2*a);
This would output 3.
I don't want to write
"a.on_multiply(2)"
Is there a way to do this?
If yes, is it possible to do this with arrays or matrixes also?
The simplest way I can think of to make the above example work is to assign a function named a, and have the context as a parameter of that function:
function a(context) {
return (context * 2) - 1;
}
And if you really wanted a to be a function assigned to a name:
const a = context => 2 * context - 1;
And the above in ES5 syntax:
const a = functipn(context) {
return (context * 2) - 1;
}
Hopefully this helps!

Performing assignment operations on an object

Example JSFiddle so you can get a better idea of what is going on http://jsfiddle.net/brsXL/3/ (open your console and view the logged vars object).
I am building a parser and computer for a specific subset of maths in JavaScript, it takes an expression as a string from the user and allows them to use variables. To keep my computational logic simple but allow for the use of variables I have created an object that acts like a number but has the bonus of being passed by reference.
var Variable = function(value) {
this.value = value || null;
}
Variable.prototype.valueOf = function() {
return this.value;
}
This works so that:
var a = new Variable(10);
console.log(a + 2); // = 12
console.log(a / 2); // = 5
However as soon as I wish to perform any form of assignment operation such as += the object is lost and gets replaced by the result of the operation against the object's value property. e.g.
var a = new Variable(10);
console.log(a += 2); // = 12
console.log(a); // = 12
The reason I need it to work like this is because I want to use the same function to handle both numbers and variables. I could add code to each assignment operation but this feels sub-optimal to me, e.g.
var ops = {
"+=" : function(a, b) {
if (a instanceof Variable) {
a.value += b;
} else {
a += b;
}
return a;
},
...
}
But I'd much rather write:
var ops = {
"+=" : function(a, b) {
return a += b;
},
...
}
Can this be done?
I'd much rather write:
function(a, b) {
return a += b;
}
Can this be done?
No. It's impossible to pass a Reference value as a single variable. You always will need to use object properties. a is always local-scoped in your function, so changing it won't affect the outer world. And I'd discourage you from trying to make your operators functions that operate on higher-scope variables…
I think in your case it's quite fine to use an explicit test for variables, because the assignment operator has to do that actually. You cannot assign to literals or other values, only to variables. It might even be
var ops = {
"=" : function(a, b) {
if (a instanceof Variable) {
a.value = +b; // cast b to a number (from whatever it is)
return a;
} else {
throw new Error("Invalid assignment to non-variable "+a);
}
},
...
}
Also, to avoid code duplication you might not write out all the compound assignment operators. Define them in a generic way:
["+", "-", "*", "/"].forEach(function(op) {
ops[op+"="] = function(a, b) {
return ops["="].call(this, a, ops[op].call(this, a, b));
};
});
(Updated jsfiddle demo)

How to make comparison of objects `a == b` to be true? [duplicate]

This question already has answers here:
Object comparison in JavaScript [duplicate]
(10 answers)
Closed 9 years ago.
Here is one of the questions in JavaScript online-test before job interview:
function F(){};
var a = new F();
var b = new F();
Q: How to make comparison a == b to be true? (e.g. console.log(a == b) // true)
I answered that it's impossible because a and b are two different instances of F and equal comparison in JS in case of non-primitives compares reference.
But some time ago I've read article "Fake operator overloading in JavaScript" by Axel Rauschmayer: http://www.2ality.com/2011/12/fake-operator-overloading.html — and I wonder if there is a hack to fake operator overload in comparison of objects?
It really depends on what they mean by "How to make comparison a == b to be true?"
If you're allowed to change the constructor, then you could make your constructor a singleton:
function F(){
if (!F.instance) {
F.instance = this;
} else {
return F.instance;
}
};
var a = new F();
var b = new F();
if (a === b) {
//they are the same
}
If they want you to keep everything as it is but have a comparision that contains a == b then you could write the following:
if ("" + a == b) {
}
If they want to know methods of determine whether the two objects are instances of the same constructor function, then you could compare the constructor property or the __proto__ property:
if (a.constructor === b.constructor) {
}
if (a.__proto__ === b.__proto__) {
}
If they want to know methods of dermine whether these two objects have the same properties, you can either compare their JSON string:
if (JSON.stringify(a) === JSON.stringify(b)) {
}
or you write a function that recursively compares all the properties in both objects (deep comparision).
And the most simple answer to the question "How to make comparison a == b to be true?":
var a = new F();
var b = new F();
b = a;
if (a === b) {
//surprise!!!
}
my best answer would be this since you can compare different functions:
console.log(a.constructor+"" === b.constructor+"");
as it returns the functions as strings and then compare them literally .
example test:
function f1(){}
function f2(){}
var a = new f1(),
b= new f2();
console.log(a.constructor+"" === b.constructor+"");
b = new f1();
console.log(a.constructor+"" === b.constructor+"");
DEMO
note: the === sign is not needed as the third would be for type comparison and both are strings at that point so using == would do exactly the same thing
EDIT: my actual answer to the question however would be: by removing new from the initialization

Categories

Resources