是否可以编写适用于每个名称的函数?

Is it possible to write a function that applies to every name?

是否可以为一个对象提供一个函数,无论函数名称如何,该函数在调用时总是被调用?

或者换句话说:是否可以有一个适用于所有可能名称的函数?

也许对象的一些变化 prototype?

这是一个如何工作的例子:

const o = {
  [magic here]: () => 1;
};

o.foo(); // returns 1
o.bar(); // returns 1
o.baz(); // returns 1

编辑以澄清我为什么要这样做:

我正在试验一种铁路编程方法。 基本上不是手动检查对象是 null 还是 undefined 并做出相应的反应,我希望它是自动化的。

示例:


// checks if object is null and returns a object, that can be called however without crashing
// thanks to T.J. Crowder's answer
function saveNull(o){
  if(o !== null) return o;

  const p = new Proxy({}, {
    get(target, prop, receiver) {
      return () => p;
    },
  });

  return p;
}

const a = " abc"; // could be null

const b = a.toUpperCase().trim(); // could crash
const c = a ? a.toUpperCase.trim() : null; // approach 1
const d = a && a.toUpperCase().trim(); // approach 2
const e = saveNull(a).toUpperCase().trim(); // approach 3

我发现最后一种方法更具可读性,也更有趣。

您可以在 ES2015 及更高版本中使用 Proxy 执行此操作;你不能在 ES5 及以下版本中这样做。

如果你真的想要每一个可能的属性到return这个神奇的功能,那么它相当简单:

const obj = {};
const magic = () => 1;
const p = new Proxy(obj, {
  get(target, prop, receiver) {
    return magic;
  }
});

console.log(p.foo());     // returns 1
console.log(p.bar());     // returns 1
console.log(p.baz());     // returns 1

如果你想让对象拥有其他属性,并且 return 它们的值(如果它们存在)但魔法函数不存在的话,你可以使用 Reflect.has to see if the object has the property, and then Reflect.get 来获取它,如果所以:

const obj = {
  notMagic: 42
};
const magic = () => 1;
const p = new Proxy(obj, {
  get(target, prop, receiver) {
    // If the object actually has the property, return its value
    if (Reflect.has(target, prop)) {
      return Reflect.get(target, prop, receiver);
    }
    // Return the magic function
    return magic;
  }
});

console.log(p.foo());     // returns 1
console.log(p.bar());     // returns 1
console.log(p.baz());     // returns 1
console.log(p.notMagic);  // 42

如果您希望该函数将 this 视为对象,您可以使用 non-arrow 函数并可能使用 bind 以保持简单:

const obj = {
  notMagic: 42
};
const magic = function() {
  console.log(this === obj);
  return 1;
}.bind(obj);
const p = new Proxy(obj, {
  get(target, prop, receiver) {
    // If the object actually has the property, return its value
    if (Reflect.has(target, prop)) {
      return Reflect.get(target, prop, receiver);
    }
    // Return the magic function
    return magic;
  }
});

console.log(p.foo());     // returns 1
console.log(p.bar());     // returns 1
console.log(p.baz());     // returns 1
console.log(p.notMagic);  // 42