Могу ли я определить пользовательские перегрузки операторов в Javascript?
Можно ли определить пользовательские операторы между экземплярами типа в JavaScript?
Например, если у меня есть пользовательский векторный класс, можно ли использовать
vect1 == vect2
чтобы проверить равенство, в то время как базовый код будет примерно таким?
operator ==(a, b) {
return a.x == b.x && a.y == b.y && a.z == b.z;
}
(Это, конечно, бессмыслица.)
Ответы
Ответ 1
Я согласен с тем, что равная функция на векторном прототипе является наилучшим решением. Обратите внимание, что вы также можете создавать другие инфиксные операторы посредством цепочки.
function Vector(x, y, z) {
this.x = x;
this.y = y;
this.z = z;
}
Vector.prototype.add = function (v2) {
var v = new Vector(this.x + v2.x,
this.y + v2.y,
this.z + v2.z);
return v;
}
Vector.prototype.equal = function (v2) {
return this.x == v2.x && this.y == v2.y && this.z == v2.z;
}
Здесь вы можете найти онлайн-образец.
Обновление: здесь представлена более обширная выборка создания Factory функции, которая поддерживает цепочку.
Ответ 2
Нет, JavaScript не поддерживает перегрузку оператора. Вам нужно будет написать метод, который делает это:
Vector.prototype.equalTo = function(other) {
if (!(other instanceof Vector)) return false;
return a.x == b.x && a.y == b.y && a.z == b.z;
}
Затем вы можете использовать этот метод, например:
vect1.equalTo(vect2)
Ответ 3
Лучшее, что вы можете сделать, если хотите придерживаться оператора ==
:
function Vector(x, y, z) {
this.x = x;
this.y = y;
this.z = z;
}
Vector.prototype.toString = function () {
return this.x + ";" + this.y + ";" + this.z;
};
var a = new Vector(1, 2, 3);
var b = new Vector(1, 2, 3);
var c = new Vector(4, 5, 6);
alert( String(a) == b ); // true
alert( String(a) == c ); // false
alert( a == b + "" ); // true again (no object wrapper but a bit more ugly)
Ответ 4
Нет, это не часть спецификации (это не значит, что нет некоторые хаки).
Ответ 5
Вы можете изменять встроенные методы объектов в JavaScript, например метод valueOf()
. Для любых двух объектов применяются следующие операторы >, <, <=, >=, -, +
JavaScript принимает свойство valueOf()
каждого объекта, поэтому он имеет дело с такими типами операторов: obj1.valueOf() == obj2.valueOf()
(это происходит за кулисами). Вы можете перезаписать метод valueOf()
, который зависит от ваших потребностей. Так, например:
var Person = function(age, name){
this.age = age;
this.name = name;
}
Person.prototype.valueOf(){
return this.age;
}
var p1 = new Person(20, "Bob"),
p2 = new Person(30, "Bony");
console.log(p1 > p2); //false
console.log(p1 < p2); //true
console.log(p2 - p1); //10
console.log(p2 + p1); //40
//for == you should the following
console.log(p2 >= p1 && p2 <= p1); // false
Итак, это не точный ответ на ваш вопрос, но я думаю, что это может быть полезным для такого рода вопросов.
Ответ 6
Вот простая эмуляция, которая проверяет равенство, используя сторожевой оператор:
function operator(node)
{
// Abstract the guard operator
var guard = " && ";
// Abstract the return statement
var action = "return ";
// return a function which compares two vector arguments
return Function("a,b", action + "a.x" + node + "b.x" + guard + "a.y" + node + "b.y" + guard + "a.z" + node + "a.z" );
}
//Pass equals to operator; pass vectors to returned Function
var foo = operator("==")({"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3});
var bar = operator("==")({"x":1,"y":2,"z":3},{"x":4,"y":5,"z":6});
//Result
console.log(["foo",foo,"bar",bar]);
Для нестрогих режимов функции индекс массива (определенный в 15.4), названный свойствами данных объекта аргументов, числовые значения которых меньше числа формальных параметров соответствующего функционального объекта, сначала разделяют их значения с соответствующими привязками аргументов в контексте выполнения функций. Это означает, что изменение свойства изменяет соответствующее значение привязки аргумента и наоборот. Это соответствие прерывается, если такое свойство удаляется, а затем переопределяется или свойство изменяется в свойство accessor. Для функций строгого режима значения свойств объекта аргументов являются просто копией аргументов, переданных функции, и между значениями свойств и формальными значениями параметров нет динамической связи.
Ссылки
Ответ 7
Это не прямой ответ на ваш вопрос, но стоит отметить.
PaperScript - это простое расширение JavaScript, которое добавляет поддержку перегрузки оператора любому объекту.
Он используется для создания векторной графики поверх холста HTML5.
Разбираем PaperScript в JavaScript на теге script с типом = "text/paperscript":
<!DOCTYPE html>
<html>
<head>
<!-- Load the Paper.js library -->
<script type="text/javascript" src="js/paper.js"></script>
<!-- Define inlined PaperScript associate it with myCanvas -->
<script type="text/paperscript" canvas="myCanvas">
// Define a point to start with
var point1 = new Point(10, 20);
// Create a second point that is 4 times the first one.
// This is the same as creating a new point with x and y
// of point1 multiplied by 4:
var point2 = point1 * 4;
console.log(point2); // { x: 40, y: 80 }
// Now we calculate the difference between the two.
var point3 = point2 - point1;
console.log(point3); // { x: 30, y: 60 }
// Create yet another point, with a numeric value added to point3:
var point4 = point3 + 30;
console.log(point4); // { x: 60, y: 90 }
// How about a third of that?
var point5 = point4 / 3;
console.log(point5); // { x: 20, y: 30 }
// Multiplying two points with each other multiplies each
// coordinate seperately
var point6 = point5 * new Point(3, 2);
console.log(point6); // { x: 60, y: 60 }
var point7 = new Point(10, 20);
var point8 = point7 + { x: 100, y: 100 };
console.log(point8); // { x: 110, y: 120 }
// Adding size objects to points work too,
// forcing them to be converted to a point first
var point9 = point8 + new Size(50, 100);
console.log(point9); // { x: 160, y: 220 }
// And using the object notation for size works just as well:
var point10 = point9 + { width: 40, height: 80 };
console.log(point10); // { x: 200, y: 300 }
// How about adding a point in array notation instead?
var point5 = point10 + [100, 0];
console.log(point5); // { x: 300, y: 300 }
</script>
</head>
<body>
<canvas id="myCanvas" resize></canvas>
</body>
</html>