Могу ли я определить пользовательские перегрузки операторов в 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>