简体   繁体   中英

How to intercept a known property value assignment of an unknwon object created using literal notation

This question is a continuation of another I asked here: How to intercept and modify a specific property for any Object

This is a method used to intercept any object's property of a certain name with the objective of changing the value or do a certain action when it is assigned or read:

 Object.defineProperty(Object.prototype, "my_property", { set: function (value) { this._value = value; }, get: function () { return "changed"; } }); var some_object = {}; some_object.my_property = "unchanged"; document.body.innerHTML += some_object.my_property; 
 My property value is: 

While that method is working fine for values assigned to or read from properties after the object has been created, example:

var some_object = {}; // or new Object()
some_object.some_property = "some_value"; // triggers setter
console.log(some_object.some_property);   // triggers getter

It won't trigger the getter and setter if the property has been initialized together with the object using literal notation, like so:

var some_object = {some_property: "some_value"}; // does not trigger setter
console.log(some_object.some_property);          // does not trigger getter

How can I adapt the previous strategy so that it can also work with the literal notation or is there a different way of achieving this using a completely different method? Perhaps by intercepting the creation of any object through literal notation, similar to monkey patching the Object.create() function?

Keep in mind that this is only to target a property of a known name on any unknown object.

There's no way I know of to achieve the effect you're looking for. An assignment with = will cause your object to go through the Prototype chain and use the get method on the Object prototype. However, a literal assignment will place it directly on your new object. It's the rules of Javascript. For more information I'd suggest reading You Don't Know JS, This & Object Prototypes, Chapter 5, specifically the Setting & Shadowing Properties section.

Relevant part:

We will now examine three scenarios for the myObject.foo = "bar" assignment when foo is not already on myObject directly, but is at a higher level of myObject's [[Prototype]] chain:

  1. If a normal data accessor (see Chapter 3) property named foo is found anywhere higher on the [[Prototype]] chain, and it's not marked as read-only (writable:false) then a new property called foo is added directly to myObject, resulting in a shadowed property.
  2. If a foo is found higher on the [[Prototype]] chain, but it's marked as read-only (writable:false), then both the setting of that existing property as well as the creation of the shadowed property on myObject are disallowed. If the code is running in strict mode, an error will be thrown. Otherwise, the setting of the property value will silently be ignored. Either way, no shadowing occurs.
  3. If a foo is found higher on the [[Prototype]] chain and it's a setter (see Chapter 3), then the setter will always be called. No foo will be added to (aka, shadowed on) myObject, nor will the foo setter be redefined. Most developers assume that assignment of a property ([[Put]]) will always result in shadowing if the property already exists higher on the [[Prototype]] chain, but as you can see, that's only true in one (#1) of the three situations just described.

If you want to shadow foo in cases #2 and #3, you cannot use = assignment, but must instead use Object.defineProperty(..) (see Chapter 3) to add foo to myObject.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM