这是不可能的,使用defineProperty设置函数来实际设置属性值?

时间:2018-04-13 17:51:48

标签: javascript defineproperty

我想使用vanilla JavaScript实现双向数据绑定(如Angular或Vue)。

模型部分的视图我可以使用添加输入事件监听器, 以及查看部分的模型,我想使用Object.defineProperty的set函数。

在defineProperty的set函数中,我需要更改视图的值并设置属性值,但是会导致“超出最大调用堆栈大小”, 因为set property value将一次又一次地递归运行。

现在的问题是:有没有办法可以同时使用set函数并设置其属性值?

现在我的代码:

<!DOCTYPE html>
<html>
<head lang="en">
  <meta charset="UTF-8">
  <title>2 Way Data Binding</title>
</head>
<body>
  text: <input id="text" class="text" type="text">
</body>

<script type="text/javascript">

  var input = document.querySelector("#text");
  var data = {};
  Object.defineProperty(data, "text", {

    get: function(){
        return input.value
    },
    set: function(newValue){

      input.value = newValue;
      // data.text = newValue;  // <------ this is the problem
    }
  })

  input.input = function(){
    data.text = data.text;
  }

</script>
</html>

2 个答案:

答案 0 :(得分:1)

回答你的问题 - 不。如果你有一个setter,你就可以转身并设置值而不需要循环。另一种方法是在对象上拥有一个私有属性,只有get()set()方法才能与之交互。外部世界将仅使用具有getter / setter的属性。

不确定这是否是实现绑定的好方法,但它是一种使用setter来设置属性的方法:

&#13;
&#13;
const data = {
  // _text is the source of truth
  _text: "some text",
  get text() {
    return this._text
  },
  set text(newValue) {
    input.value = newValue;
    this._text = newValue;
  }
};

const input = {
  value: data.text
}

// original value
console.log(data.text)
console.log(input.value)

// change it
data.text = "other text"
console.log(data.text)
console.log(input.value)
&#13;
&#13;
&#13;

答案 1 :(得分:0)

  

在setter函数中我需要设置属性值,但是它会导致&#34;超出最大调用堆栈大小&#34;,因为set属性值会一次又一次地递归运行。

是。不要这样做。设置input.value就足够了,getter已经报告了新值。

  

当我在console.log中我的视图模型(在我上面的代码中是数据)时,结果是{}(一个空对象)。所以说,如果我想迭代我的视图模型,那就无法完成。

这是一个非常不同的问题。通过制作属性enumerable

可以轻松解决这个问题
var input = document.querySelector("#text");
var data = {};
Object.defineProperty(data, "text", {
    enumerable: true,
    get: function(){
        return input.value
    },
    set: function(newValue){
        input.value = newValue;
    }
});
console.log(data);