【问题标题】:Is it possible to modify defined getter function?是否可以修改定义的 getter 函数?
【发布时间】:2017-08-28 05:46:26
【问题描述】:

在微信小程序平台(基于微信应用程序的javascript +原生混合)上开发性能评估工具,我正在尝试将代码注入其原型,例如wx.request函数。

这就是你将如何使用wx.request 函数:

wx.request({
  url: 'test.php',
  data: {
     x: '' ,
     y: ''
  },
  header: {
      'content-type': 'application/json'
  },
  success: function(res) {
    console.log(res.data)
  }
})

所以为了知道请求花费了多长时间而无需手动编写添加所有锚点,我尝试通过以下方式注入代码:

var owxrequest = wx.request
wx.request = function() {
  console.log('test', Date.now())
  return owxrequest.apply(owxrequest, arguments)
}

这失败了,我收到了Cannot set property "prop" of #<Object> which has only a getter 错误。

所以我意识到对象的定义必须类似于:

wx = {
  request: get function(){
    ...
  }
  ...
}

所以我尝试了:

var owxrequest = wx.request
Object.defineProperty(wx, 'request', {
  get: function() {
    console.log('test', Date.now())
    return owxrequest.apply(owxrequest, arguments)
  }
})

此操作失败并出现错误 (request: fail parameter error: parameter.url should be String instead of Undefined)。然后我尝试了:

var owxrequest = wx.request
Object.defineProperty(wx, 'request', {
  set: function() {
    console.log('test', Date.now())
    return owxrequest.apply(owxrequest, arguments)
  }
})

这不会引发错误,但在调用wx.request()时也没有效果...

【问题讨论】:

    标签: javascript wechat


    【解决方案1】:

    您可以通过重新定义 getter 来实现这一点。重点是:重新定义的 getter 应该返回一个函数对象,因为 wx.request 是一个函数:

    Object.defineProperty(wx, 'request', {
      get: function() {
        return function() {
          //...
        };
      }
    });
    

    为什么我会收到错误消息:request: fail parameter error: parameter.url should be String instead of Undefined

    您正在尝试访问 getter 本身的 argumentsget: function(){...} 中的函数 arguments)。这个arguments 是一个空对象,可以通过console.log() 语句来验证。因为它是空的,arguments.url 是未定义的,这就是 wx 抱怨参数的原因。

    这是一个工作示例:

    let wx = {
      get request(){
        return function() {
          console.log(10);
          return 88;
        };
      }
    };
    
    let oldF = wx.request;
    
    Object.defineProperty(wx, 'request', {
      get: function() {
        return function() {
          console.log(new Date());
          return oldF.apply(wx, arguments);
        };
      }
    });
    
    console.log(wx.request());
    

    上面的代码会打印:

    2017-08-28T06:14:15.583Z // timestamp
    10
    88
    

    【讨论】:

    • 这就是你定义吸气剂的方式,我明白了!
    • @AeroWang 我还添加了对所提到的错误的解释。请检查。
    【解决方案2】:

    您可以只屏蔽request 函数。 简单例子:

    遮蔽吸气剂:

    // original getter latest
    let base = {
      num: 1,
      get latest() {
        return this.num;
      }
    }
    console.log(base.latest);
    
    // shadowing getter latest
    Object.defineProperty(base, 'latest', {
      get: function() {
        return this.num + 1;
      }
    });
    
    console.log(base.latest);

    简单的对象属性阴影

    // your original object
    let base = {
        request(){
            console.log('request original');
        }
    };
    
    base.request()
    
    
    base.request = () => {
        console.log('request new implementation');
    };
     
    // now shadow the original request implementation
    base.request()

    【讨论】:

    • 如果我不关心保留原始 wx.request 函数,这将起作用,但在这里我确实需要保留它(无法访问原始代码,所以我不知道秘密密钥和加密算法来完成请求)。
    • 感谢您的澄清,我不清楚您无权访问原始代码。在这种情况下,我可以建议查看面向方面的编程,这可能很难跟踪代码执行的时间。
    猜你喜欢
    • 2017-02-23
    • 1970-01-01
    • 1970-01-01
    • 2012-05-26
    • 2011-01-23
    • 1970-01-01
    • 1970-01-01
    • 2023-04-09
    • 1970-01-01
    相关资源
    最近更新 更多