How to get object itself in custom Object.prototype.xxx function?

穿精又带淫゛_ 提交于 2020-01-05 08:51:47

问题


Object.prototype.getB = function() {

  // how to get the current value a
  return a.b;

};
const a = {b: 'c'};
a.getB();

As you can see, I want to make a function to all Object value. And I need to get the object value in this function then do something.


回答1:


Monkey Patching

What you want to do is called monkey patching — you mutate a built-in prototype. There are many wrong ways to do it, but I’ll demonstrate a way that is currently the most correct way.

Methods

In your case, the function body should return this.b. You can get the object itself with the this keyword.

If you really want to monkey-patch, check for the function’s existence beforehand and make the property writable, configurable and non-enumerable. Extracting the method makes getB a non-constructible method. All this ensures that getB behaves very much like existing built-in methods (or methods provided by the host environment).

if(!Object.prototype.hasOwnProperty("getB")){
  Object.defineProperty(Object.prototype, "getB", {
    enumerable: false,
    writable: true,
    configurable: true,
    value: {
      getB(){
        return this.b;
      }
    }.getB
  });
}

If you can’t support methods, use this instead:

if(!Object.prototype.hasOwnProperty("getB")){
  Object.defineProperty(Object.prototype, "getB", {
    enumerable: false,
    writable: true,
    configurable: true,
    value: function getB(){
      return this.b;
    }
  });
}

Keep in mind that arrow functions cannot be used for this purpose since they don’t create their own this context.

Getters / Setters

An alternative is to use a getter. Consider this:

const arr = [
    "a",
    "b",
    "c",
  ];

console.log(arr.indexOfB); // 1

How would an indexOfB getter on the Array prototype look like? We can’t use the above approach and replace value by get, or else we’ll get:

TypeError: property descriptors must not specify a value or be writable when a getter or setter has been specified

The property writable needs to be removed entirely from the descriptor. Next, value needs to be replaced by get:

if(!Array.prototype.hasOwnProperty("indexOfB")){
  Object.defineProperty(Array.prototype, "indexOfB", {
    enumerable: false,
    configurable: true,
    get: {
      indexOfB(){
        return this.indexOf("b");
      }
    }.indexOfB
  });
}

A setter can also be specified by adding a set property to the descriptor:

if(!Array.prototype.hasOwnProperty("indexOfB")){
  Object.defineProperty(Array.prototype, "indexOfB", {
    enumerable: false,
    configurable: true,
    get: {
      indexOfB(){
        return this.indexOf("b");
      }
    }.indexOfB,
    set: {
      indexOfB(newValue){
        // `newValue` is the assigned value.
        // Use `this` for the current Array instance.
        // No `return` necessary.
      }
    }.indexOfB
  });
}


来源:https://stackoverflow.com/questions/46491209/how-to-get-object-itself-in-custom-object-prototype-xxx-function

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!