Что делает оператор return внутри сеттера?

У меня есть следующий код:

var o = {};
o.a = 1;

var _value = 1;
Object.defineProperty(o,"a",{
    set: function(value){
        _value = value + 1;
        console.log("log: ", value, _value);
        return _value;
    },
    get: function(){
        return _value;
    }
});

В методе установки я увеличиваю значение _value на единицу, прежде чем вернуть его. Поэтому, если я установлю oa = 5, я ожидаю, что консоль напечатает 6 (хотя я понимаю, что возвращать значение из установщика обычно не имеет смысла). Однако, как показано в следующем фрагменте, консоль печатает 5:

> o.a = 5;
log: 5 6 // from console.log;
5 // return; why does it == value and not value + 1?
> o.a;
6
> var i = o.a = 5;
> i;
5
> o.a;
6

Итак, мой вопрос, почему он возвращает 5 а не 6?

Я надеюсь, что это не потому, что я сделал глупую ошибку в коде.

Ответ 1

Давайте посмотрим на простое назначение:

11.13.1 Простое назначение (=)

Вывод Assignment Production: LeftHandSideExpression = AssignmentExpression оценивается следующим образом:

  1. Пусть lref является результатом оценки LeftHandSideExpression.
  2. Пусть rref является результатом вычисления AssignmentExpression.
  3. Пусть rval - GetValue (rref).

Таким образом, rval присваивается значение, которое будет назначено левой стороне (oa). В вашем случае 5.

  1. Выбросьте исключение SyntaxError, если все условия истинны: [...]
  2. Вызовите PutValue (lref, rval).

Здесь значение присваивается левой стороне (PutValue(oa, 5)). Как вы можете видеть, ничего не делается с тем, PutValue возвращает PutValue (он ничего не возвращает).

  1. Возвращает rval.

Он просто возвращает значение, которое было назначено, в вашем случае 5.


Выражение присваивания всегда возвращает значение, которое было назначено.

Ответ 2

Вы ничего не можете вернуть из средства настройки свойств и просто получаете значение присваивания (это 5 потому что вы назначили 5).

что делает возврат в сеттер?

Ничего. Лучше удалите этот оператор return. В лучшем случае это игнорировалось.

Ответ 3

Значение выражения присваивания всегда равно присваиваемому значению:

var a;
console.log(a = 7); // logs 7

Это верно, независимо от того, является ли то, что вы назначаете, это переменная, свойство plain, setter, свойство только для чтения или что-то еще:

var a = {};
Object.defineProperty(a, "b", { value: 8, writable: false });
console.log(a.b = 9);  // logs 9
console.log(a.b);      // logs 8, because a.b is read-only

Как вы сказали сами, возвращаемое значение в сеттере бессмысленно, поэтому, когда вы использовали возвращаемое значение в своем сеттере, почему вы ожидали, что он действительно сделает что-нибудь особенное?

Ответ 4

Для меня, если я не делаю parseInt, он видит это как строку... Кроме того, вы не должны возвращать значение в setter. Этот код работает:

<html>
<head>
  <script language="javascript" type="text/javascript">
    var o = {};
    o.a = 1;

    var _value = 1;
    Object.defineProperty(o,"a",{
      set: function(value){
        _value = parseInt(value) + 1;
        console.log("log: ", value,_value);
      },
      get: function(){
        return _value;
      }
    });

    function setValueAndRefresh() {
      before = o.a;
      o.a = document.forms["myform"].input.value;
      alert("before: " + before + "; after: " + o.a);
    }
  </script>
</head>

<body>
  <form name="myform">
    value: <input type="text" name="input" value="5" /> <input type="button" value="set" onclick="setValueAndRefresh()"/>
  </form>
</body>
</html>