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

时间:2019-05-23 14:30:58

标签: javascript prototype

是否有可能向对象提供一个函数,而无论其名称如何,该函数总是在被调用时被调用?

或者换句话说:是否有可能具有适用于所有可能名称的功能?

也许对象的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

我发现最后一种方法更具可读性和趣味性。

1 个答案:

答案 0 :(得分:10)

您可以在ES2015及更高版本中使用Proxy来执行此操作;您无法在ES5及更低版本中做到这一点。

如果您确实希望每个可能的属性都返回此魔术函数,那么这很简单:

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

如果要允许对象具有其他属性,如果存在则返回其值,否则返回魔术函数,则可以使用Reflect.has来查看对象是否具有该属性,并且然后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视为对象,则可以使用非箭头函数,并且可能使用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