通过Object.defineProperty实现的监听函数为什么只能执行一个监听?

如下代码,通过Object.defineProperty实现的监听函数为什么只能执行一个监听——执行了最后一个监听过程,而第一个监听过程却没有运行,求解原因?

// 定义对象,包含属性uid初始化为1
let obj={
    uid:0
};

// 监听函数
function watch (callback) {
    Object.defineProperty(obj,'uid',{
        get:function(){
            return uid;
        },
        set:function(newValue){
            uid=newValue;
            console.log('set :',newValue);
            //需要触发的渲染函数可以写在这...
            callback();
        }
    })
};

//3秒后修改obj.uid的值
setTimeout(function () {obj.uid=100001;},3000)

//监听a以及后续操作
function func_a(){
    watch(function(){console.log("后续操作——1")})
}

//监听b以及后续操作
function func_b(){
    watch(function(){console.log("后续操作——2")})
}

func_a()
func_b()

结果是这样的:

set : 10001
后续操作——2
阅读 3.7k
3 个回答

你本身的问题

// 定义对象,包含属性uid初始化为1
  let obj = {
    uid: 0,
  };

  // 监听函数
  function watch(callback) {
    const descriptor = Object.getOwnPropertyDescriptor(obj, 'uid');

    Object.defineProperty(obj, 'uid', {
      get: function() {
        return uid;
      },
      set: function(newValue) {
        uid = newValue;
        console.log(descriptor);
        if (descriptor && descriptor.set) {
          descriptor.set(newValue);
        }
        console.log('set :', newValue);
        //需要触发的渲染函数可以写在这...
        callback();
      },
    });
  }

  //3秒后修改obj.uid的值
  setTimeout(function() {
    obj.uid = 100001;
  }, 3000);

  //监听a以及后续操作
  function func_a() {
    watch(function() {
      console.log('后续操作——1');
    });
  }

  //监听b以及后续操作
  function func_b() {
    watch(function() {
      console.log('后续操作——2');
    });
  }

  func_a();
  func_b();

更好地实现.

一个带有已发布事件的事件监听器就可以了

不多要求的话,做成监听队列,依次调用监听回调函数。

clipboard.png

我觉得不用想得太复杂

// 定义对象,包含属性uid初始化为1
let obj = {
    uid: 0
}

let isLoginSuccess = false // 是否已经登录成功

function login(loginData, success, fail) {
    // let isLoginSuccess = sessionStorage.getItem('isLoginSuccess')
    if (!isLoginSuccess) {
        // 登录操作,若果跨页面的话,可以考虑 用户是否登录 用sessionStorage来保存
        // sessionStorage.setItem('isLoginSuccess', true)
        loginData.uid = 10001
        isLoginSuccess = true

        success()
        return true
    }
    return false
}

login(obj, function () { console.log("第一个登录成功") })
login(obj, function () { console.log("第二个登录成功") })

"defineProperty" 是定义 property ,不是添加监听。

所以当你重新定义同一个 property 的时候,之前的定义就被覆盖了。于是第一个监听就不存在了。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题