【问题标题】:How to get getter/setter name in JavaScript/TypeScript?如何在 JavaScript/TypeScript 中获取 getter/setter 名称?
【发布时间】:2020-01-13 16:18:33
【问题描述】:

获取函数名是pretty straightforward:

const func1 = function() {}

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

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

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

但是,我怎样才能获得 getter/setter 的 字符串名称

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

const obj = new Example();

重要提示:

不想想使用硬编码字符串:

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

但是得到名字,例如:

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

【问题讨论】:

  • 我的问题显然不是重复的,因为我不想通过字符串名称访问 getter,而是要获取它的字符串表示形式。
  • @NicholasTower 我认为打字稿在这里实际上很重要,其想法是构造是类型安全的。
  • 你不能。使用 get 或 set 创建的属性被视为“伪”属性。您必须知道道具的字符串名称才能使用它,并且它是不可发现的。所以其他人说“你可以找到hello”道具是正确的——但你必须知道hello
  • 请,请,请,请澄清您的问题!不在 cmets 中,实际编辑您的问题,以反映您的真实意图!

标签: javascript typescript getter-setter


【解决方案1】:

该语法设置hello 属性描述符的get 函数,因此函数的名称将始终为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 中获取 getter/setter 名称?”它永远是“get”

编辑:
一旦你调用了obj.hello,getter 就已经被调用了,你所拥有的只是原始结果,但你可以在属性值上使用元数据。

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>

【讨论】:

  • 不,它没有回答这个问题。您的代码所做的只是为名为“hello”的伪属性创建一个 getter,然后使用字符串 hello 简单地返回您刚刚设置的属性名称,即字符串 hello。应该澄清这个问题,但真正的问题是“如何在不使用属性名称查找的情况下反映使用 setter 或 getter 创建的属性名称?”。那是做不到的。
  • 我没有看到“如何在不使用属性名称查找的情况下反映使用 setter 或 getter 创建的属性名称?”原始问题中的任何地方。你还说“你的代码所做的就是为名为'hello'的伪属性创建一个getter”,但这直接来自原始问题。
  • OP 编辑​​了这个问题,以澄清 OP 具​​体想要做你的回答建议 OP 做的事情。
  • 我添加了一个“编辑”部分作为回应
  • 我删除了我的反对票以支持怀疑。真实的,真正的答案是 - 你不能做 OP 想做的事 - 它是不可发现的。
猜你喜欢
  • 2020-07-13
  • 2020-02-09
  • 2011-05-20
  • 2023-03-07
  • 2016-02-08
  • 2018-11-30
  • 2010-11-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多