如何检测何时在JavaScript中调用对象

时间:2019-02-28 21:03:51

标签: javascript

如何检测何时访问JavaScript对象?我的意思是像范围对象,而不是全局对象或对象的属性。我希望能够执行以下操作:

"use strict"
!function() {
    var o = {
        onaccess: function() {
            console.log("o was accessed");
        }
    }
    var x = o; //"o was accessed" when this happens.
}();

2 个答案:

答案 0 :(得分:0)

您不能通过这种方式访问​​您的对象,而不是访问该对象。

您可以尝试在“全局范围”中创建吸气剂(例如,在浏览器中也称为window)或创建将吸气剂作为属性的对象,您可以将其视为“变量”在对象中”。

(function() {
    var _x = {};
    Object.defineProperty(window, 'x', {
        get: function() {
            alert("access");
            return _x;
        }
    });
    document.getElementById("g").addEventListener("click", function() {
        var a = x;
    });
    document.getElementById("w").addEventListener("click", function() {
        var a = window.x;
    });
})();
<button id="g">Access global x</button>
<button id="w">Access window x</button>

该代码之所以有效,是因为当您访问变量(在这种情况下为x)时,它将遍历上限作用域,直到找到包含该变量的作用域。最终它将在全局范围内寻找变量,即window,在这里我设置了一个将在每次调用window.x时运行的吸气剂(或简称为x,它将最终在内部访问window.x

这很骇人,我不建议您这样做,因为您必须定义一个全局变量。但是,您可以尝试在某些属性中使用getter创建对象(与window.x相同),因此不必使用全局范围,但必须始终通过以下方式访问对象属性:在对象之前:

(function() {
  var _x = {};
  var prop = {};
  Object.defineProperty(prop, 'x', {
      get: function() {
          alert("access");
          return _x;
      }
  });
  document.getElementById("w").addEventListener("click", function() {
      var a = prop.x;
  });
})();
<button id="w">Access property x</button>

请注意,这仅适用于预定义的变量名称。如果您想捕获“所有”变量,则可以使用Proxies,它不可能在全局范围(窗口)上侵入,但可以与对象一起使用,例如:

var h = {
    get: function(target, name){
        alert("Accessed property " + name);
    }
};

var p = new Proxy({}, h);

document.getElementById("x").addEventListener("click", function() {
  var a = p.x;
});
document.getElementById("y").addEventListener("click", function() {
  var a = p.y;
});
document.getElementById("r").addEventListener("click", function() {
  var a = p[Math.random()];
});
<button id="x">Access x property</button>
<button id="y">Access y property</button>
<button id="r">Access random property</button>

答案 1 :(得分:0)

您可以创建一个代理,然后在每次调用函数时都可以记录一些内容,但是请注意,尽管在IE11或更低版本中代理不是100%可填充的

function realFunction() {
    return {
       a: "5"       
    }
}

var proxy = new Proxy(realFunction, {
    get: function(target, key) {
        const obj = target();
        console.log("key", `'${key}'`, "was called on", target);
            return obj[key];
        }
    });

proxy.a // "5"