A question about encapsulating watch snooping events similar to those in vue



----

// pages/three/three.js
Page({

  /**
   * 
   */
  data: {
    name:"",
    age:"",
    sex:""
  },

 
  onLoad: function (options) {
    this.setWatch(this);
    console.log(this)
  },
  watch:{
    name(){
      console.log("name")
      console.log(111111)
    },
    age(){
      console.log(this.data.name)
      console.log("age")
    },
    sex(){
      console.log("sex")
    }
  },
  
  onReady: function () {

  },
  btn(){
   
    this.setData({
      name:1
    })
  
  },

  setWatch(){
     let watch=this.watch;
     let _this=this;
    // Object.keys(watch).forEach(v=>{
    //   console.log(v)
    //   var setVal = _this.data[v];
    //   Object.defineProperty(_this.data,v,{
    //     configurable: true,
    //     enumerable: true,
    //     get:function(){
    //       return setVal
    //     },
    //     set:function(val){
    //       setVal=val;
    //       _this.watch[v].call(_this);
    //     }
    //   })
    // })
     for(var v in watch){
       console.log(v)
       var setVal=_this.data[v];
       Object.defineProperty(_this.data,v,{
         configurable: true,
         enumerable: true,
         get:function(){
           return setVal
         },  
         set:function(val){
           setVal=val;
           console.log(_this.watch[v])
           _this.watch[v].call(_this);
         }
       })
     }
    
  }

})

when I use for (var i in obj) {} to add get and set methods to an object, the listening event is always the last method in the watch object, that is, whether I modify the value of name or age, I execute the sex method in watch, but when I add it with Object.keys (obj), the event is normal and ask the boss to solve

Nov.03,2021

replace the var of for (var v in watch) with let


if you write v in this way, you must be watch the last attribute
es6 is relatively simple. You can directly use let to declare v as a block-level scope variable to implement

.
for(let v in watch){

seeing that you are still using es5, you can write a closure and pass the key name v as a parameter

for (var v in watch) {
  (function (v) {
    //
  })(v)
}
< hr >

explain why. You use var to declare that there is a concept of variable promoting , because before es6, js does not have block-level scope, and the code you write is like this

.
setWatch(){
  for (var v in watch) {
  }
},
After the

variable is promoted, it looks like this.

setWatch() {
  var v;
  for (v in watch) {
  }
},
The result of

is that the latest attribute name in the for loop keeps assigning values to the same variable. Finally, when you read this v in the callback, the result is not what you want, you can only read the last attribute

.
Menu