【问题标题】:Trouble running an Observer Pattern example运行观察者模式示例时遇到问题
【发布时间】:2015-07-04 06:51:32
【问题描述】:

我正在尝试重现 Learning JavaScript Design Patterns 书中给出的观察者模式示例,但在 extend 函数中出现此错误:

我正在使用书中从这一行以下开始的代码:

首先,让我们为一个主题可能拥有的依赖观察者列表建模:

我已经在fiddle 中设置了代码,我想了解我收到错误的原因。

【问题讨论】:

  • 我回答的问题让您满意吗?

标签: javascript debugging design-patterns observer-pattern observers


【解决方案1】:

您的问题中报告的错误中的问题是extend() 的第一个参数不是有效对象。

当我运行你的 jsFiddle 时,它​​会报告 Observer is not defined

如果Observer() 模式应该与Subject() 模式平行,那么您缺少这段代码:

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

或者,也许你只需要改变:

extend( new Observer(), check );

到:

extend( new ObserverList(), check );

以便它使用您为ObserverList() 显示的代码。


实际上,当我按下你的jsFiddle中的按钮时,出现的错误是Uncaught ReferenceError: Observer is not defined,这进一步证实了上述情况。

而且,当我应用该更改时,代码似乎在此处运行:http://jsfiddle.net/jfriend00/8xmu1mcg/,虽然我不知道它应该做什么,但它添加了一个复选框并且没有错误。

【讨论】:

  • 我能想到的 JavaScript 中最好的例子是 node.js EventEmitter 类。你可以在这里查看代码:github.com/Wolfy87/EventEmitter/blob/master/EventEmitter.js
  • @DuncanFinney - 很好的例子。我认为 node.js 中的 EventEmitter 对象是他们拥有的最有用的实用程序对象之一,并且可能是整个 node 库中最常用于继承或混合的对象。
【解决方案2】:

唯一的问题是你忽略了定义Observer。添加函数定义后,小提琴工作:

http://jsfiddle.net/cm5a62jb/1/

// The Observer
function Observer(){
  this.update = function(){
    // ...
  };
}

function ObserverList(){
  this.observerList = [];
}
 
ObserverList.prototype.add = function( obj ){
  return this.observerList.push( obj );
};
 
ObserverList.prototype.count = function(){
  return this.observerList.length;
};
 
ObserverList.prototype.get = function( index ){
  if( index > -1 && index < this.observerList.length ){
    return this.observerList[ index ];
  }
};
 
ObserverList.prototype.indexOf = function( obj, startIndex ){
  var i = startIndex;
 
  while( i < this.observerList.length ){
    if( this.observerList[i] === obj ){
      return i;
    }
    i++;
  }
 
  return -1;
};
 
ObserverList.prototype.removeAt = function( index ){
  this.observerList.splice( index, 1 );
};

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 );
  }
};

// Extend an object with an extension
function extend( extension, obj ){
  for ( var key in extension ){
    obj[key] = extension[key];
  }
}
 
// References to our DOM elements
 
var controlCheckbox = document.getElementById( "mainCheckbox" ),
  addBtn = document.getElementById( "addNewObserver" ),
  container = document.getElementById( "observersContainer" );
 
 
// Concrete Subject
 
// Extend the controlling checkbox with the Subject class
extend( new Subject(), controlCheckbox );
 
// Clicking the checkbox will trigger notifications to its observers
controlCheckbox.onclick = function(){
  controlCheckbox.notify( controlCheckbox.checked );
};
 
addBtn.onclick = addNewObserver;
 
// Concrete Observer
 
function addNewObserver(){
 
  // Create a new checkbox to be added
  var check = document.createElement( "input" );
  check.type = "checkbox";
 
  // Extend the checkbox with the Observer class
  extend( new Observer(), check );
 
  // Override with custom update behaviour
  check.update = function( value ){
    this.checked = value;
  };
 
  // Add the new observer to our list of observers
  // for our main subject
  controlCheckbox.addObserver( check );
 
  // Append the item to the container
  container.appendChild( check );
}
<button id="addNewObserver">Add New Observer checkbox</button>
<input id="mainCheckbox" type="checkbox"/>
<div id="observersContainer"></div>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-11-25
    • 1970-01-01
    • 2012-12-01
    • 2012-11-19
    • 1970-01-01
    • 2016-02-20
    相关资源
    最近更新 更多