Как получить имя получателя / установщика в JavaScript / TypeScript? - PullRequest
1 голос
/ 13 января 2020

Получение имени функции довольно просто :

const func1 = function() {}

const object = {
  func2: function() {}
}

console.log(func1.name);
// expected output: "func1"

console.log(object.func2.name);
// expected output: "func2"

Как я могу получить имя строки метода получения / установки, хотя?

class Example {
  get hello() {
    return 'world';
  }
}

const obj = new Example();

Важное примечание:

Я не хочу использовать жестко запрограммированную строку:

Object.getOwnPropertyDescriptor(Object.getPrototypeOf(obj), 'hello')

Но получить имя, например:

console.log(getGetterName(obj.hello))
// expected output: "hello"

1 Ответ

1 голос
/ 13 января 2020

Этот синтаксис устанавливает функцию get дескриптора свойства hello, поэтому имя функции всегда будет get. Вы можете проверить, имеет ли свойство hello функцию get в своем дескрипторе свойства с помощью Object.getOwnPropertyDescriptor().

class Example {
  get hello() {
    return 'world';
  }
}
/*
compiles to / runs as
var Example = (function () {
    function Example() {
    }
    Object.defineProperty(Example.prototype, "hello", {
        get: function () {
            return 'world';
        },
        enumerable: true,
        configurable: true
    });
    return Example;
}());
*/

const des = Object.getOwnPropertyDescriptor(Example.prototype, 'hello');
console.log(des.get.name); // get (will always be 'get')

// to check if 'hello' is a getter
function isGetter(name) {
  const des = Object.getOwnPropertyDescriptor(Example.prototype, name);
  return !!des && !!des.get && typeof des.get === 'function';
}
console.log(isGetter('hello')); // true

Похоже, это не решит вашу конечную проблему, но: Object.getOwnPropertyDescriptor(Example.prototype, 'hello').get.name 100% отвечает на вопрос "Как получить имя получателя / установщика в JavaScript / TypeScript?" и это всегда будет "get"

Edit:
Как только вы позвоните obj.hello, геттер уже называется, все, что у вас есть, это примитивный результат, но вы можете использовать метаданные для значения свойства его самого.

function stringPropertyName() {
  let _internal;
  return (target, key) => {
    Object.defineProperty(target, key, {
      get: () => {
        const newString = new String(_internal);
        Reflect.defineMetadata('name', key, newString);
        return newString;
      },
      set: value => {
        _internal = value;
      }
    });
  };
}

class Example1 {
  @stringPropertyName()
  hello = 'world';
}

const obj1 = new Example1();
console.log(Reflect.getMetadata('name', obj1.hello)); // hello

class Example2 {
  _hello = 'world';
  get hello() {
    const newString = new String(this._hello);
    Reflect.defineMetadata('name', 'hello', newString);
    return newString;
  }
  set hello(value) {
    this._hello = value;
  }
}

const obj2 = new Example2();
console.log(Reflect.getMetadata('name', obj2.hello)); // hello
<script src="https://cdnjs.cloudflare.com/ajax/libs/core-js/2.6.11/core.min.js"></script>
...