-3

我需要定义名称函数以与更远的另一种方法一起使用,因此我需要对其进行动态命名。

目前...

`use strict`;
const factory = () => () => {}

const method = factory();

method.name === undefined

&&
const factory = () => { const name = () => {}; return name }

const method = factory();

method.name === "name"

因为...

`use strict`;
const factory = () => () => {}

factory() === () => {} // and () => {} is not a named method

但我想要...

`use strict`;
const factory = () => () => {}

const method = factory();

method.name === "method"

这是额外的描述,因为堆栈溢出要我说更多,但我认为问题是不言自明的

4

4 回答 4

2

使您的箭头功能成为传统的function

const factory = () => function method() {}

如果名称是动态的,那么我们必须处理函数的名称属性是只读的这一事实。函数定义可以以动态方式发生(但这涉及解析),或者我们可以创建一个代理:

const factory = () => new Proxy(() => console.log("hello"), { 
    get(obj, prop) {
        return prop === "name" ? "method" : prop;
    }
});

const method = factory();

console.log(method.name);
method();

变量的名称

在评论中您解释说动态名称应由变量名称(即method)确定,但是:

  1. 可以有许多变量引用同一个函数,而一个函数只有一个名称——这导致了一个无法解决的悖论。

  2. 变量名仅在解析时存在,在执行时不存在。

于 2021-03-12T19:00:04.053 回答
1

这行得通吗?但是,您必须重复该名称,因此不确定它是否完全符合您的要求

let factory = (name) => new Function(`return function ${name}() {}`)();
let method = factory("method");
method.name; // "method"
于 2021-03-12T19:14:57.553 回答
1

您可以通过使用动态name道具创建一个对象并将函数分配给该道具来做到这一点:

`use strict`;

const factory = s => (
    {[s]: () => {}}[s]
)

const method = factory('blah');
console.log(method.name)

于 2021-03-12T19:09:48.357 回答
0

根据@trincot 的回答,最初提出的建议是不可能的。

但是,这是我选择的足够替代方案:

`use strict`;

// @trincot's answer
const renameFunction = (name, func) => new Proxy(func, { 
  get(obj, prop) {
    return prop === "name" ? name : prop;
  }
})

const identifyFunction = (obj) => {
  if (typeof obj === "object") {
    // because the object has the original defined as a property
    // we can pull the name back out
    const name = Object.keys(obj)[0];
    const func = obj[name];
    return renameFunction(name, func)
  }
  // if it's not an object then assume it's named and return
  return obj
}

const useFooName = (foo) => {
  let _foo = foo;
  
  // only need to identify if it's an object
  if (typeof _foo === "object") {
    _foo = identifyFunction(foo)
  }

  // using both the function and its name
  console.log(`${_foo.name} ${_foo()}`);
}

const factory = (func) => func;
const foo = factory(() => "bar");

useFooName(foo)     // bar
useFooName({ foo }) // foo bar

这也可以动态使用...

`use strict`;

// @trincot's answer
const renameFunction = (name, func) => new Proxy(func, { 
  get(obj, prop) {
    return prop === "name" ? name : prop;
  }
})

const identifyFunction = (obj) => {
  if (typeof obj === "object") {
    // because the object has the original defined as a property
    // we can pull the name back out
    const name = Object.keys(obj)[0];
    const func = obj[name];
    return renameFunction(name, func)
  }
  // if it's not an object then assume it's named and return
  return obj
}

// let there be a function that accepts and function bar
// and uses bar's name; for whatever reason you don't want to
// change this method
const useBarName = (bar) => `${bar.name} ${bar()}`

// let there also be an arbitrary amount of functions using this
const traditionalWay = () => {
  const a = () => "b";
  const c = () => "d";
  const e = () => "f";

  console.log([a, c, e].map(useBarName).join(" ")); // a b c d e f ...
}

// but instead of hard-coding the functions it'd be easier
// to just build a factory that did it automatically
const brokenWay = () => {
  const factory = (letter) => () => letter;
  const a = factory("b");
  const c = factory("d");
  const e = factory("f");

  console.log([a, c, e].map(useBarName).join(" ")); // b d f ...
}

// so instead you can use the indentifyFunction to identify
// the anonymous methods
const newWay = () => {
  const factory = (letter) => () => letter;
  const a = factory("b");
  const c = factory("d");
  const e = factory("f");

  console.log([{a}, {c}, {e}].map(identifyFunction).map(useBarName).join(" ")); // a b c d e f ...
}

traditionalWay();
brokenWay();
newWay();

于 2021-03-13T05:58:14.150 回答