他のオブジェクトとそれ自体を拡張するために、それ自体に作用するJavaScript関数

chrixm:

私は確かに私が何をしようとしています何のために名前があり、私はこれは前に頼まれていると確信していますが、私は、既存の答えを見つけるのに苦労していますよ-私は正しい用語を探しておりませんので、おそらく。私はと呼ばれるJavaScript関数持ちextend()に似てObject.assign()、マージには、一緒にオブジェクト-私はへのアクセスを持っていないObject.assign私の現在の実装では。

function extend(target) {
  for (var i = 1; i < arguments.length; ++i) {
    if (typeof arguments[i] !== 'object') {
      continue;
    }
    for (var j in arguments[i]) {
      if (arguments[i].hasOwnProperty(j)) {
        if (typeof arguments[i][j] === 'object') {
          target[j] = extend({}, target[j], arguments[i][j]);
        }
        else if (!target.hasOwnProperty(j)) {
          target[j] = arguments[i][j];
        }
      }
    }
  }
  return target;
}

これは私が使用してそれを呼び出す場合は正常に動作extend(target, defaults)の内容をマージしますそのdefaults中にtarget、任意の既存のキーを上書きせずにtarget(彼らはオブジェクトであり、それらがマージされない限りは)。

私が実際に使用して、これを呼び出す方法を探していますtarget.extend(defaults)最初ので、targetへのパラメータはextend、実際として暗示されますthis私は交換することにより機能を書き換えしようとしていtargetthis、それは望ましい結果を持っていない(私は再帰を変更した方法が間違っていると思います)。

target.extend = function() {
   ...
   this[j] = this.extend(this[j], arguments[i][j]);
   ...
   return this;
};

任意のポインタ(または既存の回答への言及は)感謝していただければ幸いです。

CertainPerformance:

あなたはする機能を割り当てることができObject.prototype、あなたが探している機能を実現するために:

Object.defineProperty(
  Object.prototype,
  'extend',
  {
    enumerable: false,
    value: function() {
      const target = this;
      for (var i = 0; i < arguments.length; ++i) {
        if (typeof arguments[i] !== 'object') {
          continue;
        }
        for (var j in arguments[i]) {
          if (arguments[i].hasOwnProperty(j)) {
            if (typeof arguments[i][j] === 'object') {
              target[j] = extend({}, target[j], arguments[i][j]);
            }
            else if (!target.hasOwnProperty(j)) {
              target[j] = arguments[i][j];
            }
          }
        }
      }
      return target;
    }
  }
);


const obj = { foo: 'foo' };
obj.extend({ bar: 'bar' });
console.log(obj);

または、コードの束をクリーンアップ:

Object.defineProperty(
  Object.prototype,
  'extend',
  {
    enumerable: false,
    value: function(...args) {
      const target = this;
      for (const arg of args) {
        for (const [key, val] of Object.entries(arg)) {
          if (typeof val === 'object') extend(target[key], val);
          else target[key] = val;
        }
      }
    }
  }
);


const obj = { foo: 'foo' };
obj.extend({ bar: 'bar' });
console.log(obj);

しかし、これはある悪い考え、それは名前の衝突や混乱コードにつながる可能性があるため、。以下のようなオブジェクトがあります場合はどう

const obj = { extend: true };

何をしないobj.extend、その後のですか?(それは自身のプロパティを参照しますが、これはスクリプトライターは、スタンドアロン機能を持っている。よりよい心配する必要がありますものではありません。)

これは、まったく同じオブジェクトのヘルパーメソッドの多くは、上に存在する理由ですObject コンストラクタ、およびありませんでObject.prototypeたとえば、あなたが呼び出しObject.assign、またはObject.definePropertyではありません obj.assignobj.defineProperty

あなたが唯一の特定のオブジェクトにこの機能が必要な場合は、呼び出すことによって、プロトタイプの汚染を避けることができObject.defineProperty、それらのオブジェクトに:

const addExtend = obj => {
  Object.defineProperty(
    obj,
    'extend',
    {
      enumerable: false,
      value: function(...args) {
        const target = this;
        for (const arg of args) {
          for (const [key, val] of Object.entries(arg)) {
            if (typeof val === 'object') extend(target[key], val);
            else target[key] = val;
          }
        }
      }
    }
  );
};

const obj = { foo: 'foo' };
addExtend(obj);
obj.extend({ bar: 'bar' });
console.log(obj);

あなたは、オブジェクトが作成される場所を管理している場合は、あなたが使用できるObject.createようにextend、プロトタイプから継承されたメソッドです。

const objExtendProto = {};
Object.defineProperty(
  objExtendProto,
  'extend',
  {
    enumerable: false,
    value: function(...args) {
      const target = this;
      for (const arg of args) {
        for (const [key, val] of Object.entries(arg)) {
          if (typeof val === 'object') extend(target[key], val);
          else target[key] = val;
        }
      }
    }
  }
);

const obj = Object.create(objExtendProto);
obj.foo = 'foo';
obj.extend({ bar: 'bar' });
console.log(obj);

おすすめ

転載: http://43.154.161.224:23101/article/api/json?id=32650&siteId=1