在 JS 中使用扩展名扩展对象

Extend an object with an extension in JS

谁能给我解释一下这是怎么回事?

function extend( obj, extension ){
  for ( var key in extension ){
    obj[key] = extension[key];
  }
}

上下文:在观察者模式中使用https://addyosmani.com/resources/essentialjsdesignpatterns/book/#observerpatternjavascript

例如:

// Extend the controlling checkbox with the Subject class
extend( controlCheckbox, new Subject() );

function Subject(){
  this.observers = new ObserverList();
}

Subject.prototype.addObserver = function( observer ){
  this.observers.add( observer );
};

Subject.prototype.removeObserver = function( observer ){
  this.observers.removeAt( this.observers.indexOf( observer, 0 ) );
};

Subject.prototype.notify = function( context ){
  var observerCount = this.observers.count();
  for(var i=0; i < observerCount; i++){
    this.observers.get(i).update( context );
  }
};

我认为发生了什么: for 循环遍历我之前添加的 Subject 的属性,然后将其添加到观察者对象。

我不明白的是:为什么它只添加了我之前添加的那些属性(即观察者、addObserver、removeObserver、notify)而不是扩展对象的 ALL 属性?

例如,当我打印出扩展对象时,我可以看到添加了 constructor- 或 __proto__ 属性 NOT .

函数extend使obj继承extension的属性和方法。

因此,在这种情况下,controlCheckbox 继承了 Subject 的属性和方法。

您将从 Subject 获得所有属性和方法,但 __proto__ 不是 属性 或方法 - 它是查找链中用于解析的实际对象方法等。有一个很好的 post here 讨论 __proto__

更新 事实上,proto 是一个 属性——但它是一种特殊的 属性。 From here:

Contains a reference to the internal prototype of the specified object.

An object can have only a single prototype (not including inherited prototypes in the prototype chain)...

因此在链中,您将有一个 __proto__ 用于 controlCheckbox 并且其 __proto__ 的属性之一应该是 __proto__ 来自 Subjects 包含其所有属性和方法。

更新 2 使用 for (propName in obj) 循环时,不会添加 proto 属性 因为它不可枚举。仅返回可枚举的继承属性。您可以搜索 EnumerablepropertyIsEnumerable() 以获取更多信息。