回调常见的模式,但为什么呢?

时间:2012-05-06 17:19:52

标签: javascript callback

我从来没有真正使用过JavaScript,但我大致知道它是什么。现在我正在查看一些chrome扩展的例子,我看到这个“模式”非常多。

var Main = {
    enable: function(){ window.addEventListener('mousemove', onMouseMove, false); },
    onMouseMove: function(event){ _onMouseMove(event) },
    _onMouseMove: function(event){
        ...lenghty implementation...
    }
}

我的问题是,为什么?这是某种优化吗?

4 个答案:

答案 0 :(得分:3)

你的问题有点模糊;但我猜你在问为什么开发人员有两种onMouseMove方法,而不只是在一种方法中完成所有工作,即:

var Main = {
    onMouseMove: function(event) { 
        // Why not just have the implementation here?
        // Why are we delegating it to the other method?
        _onMouseMove(event) 
    },
    _onMouseMove: function(event){
        // ...length implementation...
    }
}

答案是因为scope is handled in JavaScript的原因。简而言之,大多数经典OOP语言中的this关键字(如Java)总是引用函数范围内的父类(Main) - JavaScript不能像这样工作。

由于JavaScript中没有经典类,this关键字实际上是指调用它的函数;这就是new关键字在通过构造函数创建新对象时产生这种差异的原因;例如:

function MyConstructor = function () { 
    // Assign a member property
    this.aProperty = "An Example";
}

// Using the new keyword; a new scope is created for the call which refers to the
// object about to be created (and returned).
var withNew = new MyConstructor();
console.log(withNew.aProperty);  // 'An Example'

// Without the new keyword...
var withoutNew = MyConstructor();
console.log(withoutNew.aProperty);  // undefined

// Because we didn't use new, the calling function scope was applied, so 
// the `this` keyword resolves caller's scope.
console.log(this.aProperty)  // 'An Example'

通过从onMouseMove委派给_onMouseMove,范围仍然绑定到Main对象,而不是绑定到触发鼠标事件的对象。实现此目的的另一种更易读的方法是使用委托,或者如果您使用的是ES5,Function.bind

var Main = {
    enable: function() {
        window.addEventListener('mousemove', onMouseMove.bind(this), false); 
    },
    onMouseMove: function(event) { 
        // ...lengthy implementation...
    }
}

答案 1 :(得分:1)

我不熟悉chrome扩展的实现方式,但是当我使用这种模式时,它专门用于保护我的实现。

通常,您的插件会公开某些属性和功能。该功能的用户可以轻松(甚至意外地)覆盖您的暴露功能。在这种情况下,如果你在该函数中有实际的实现,它就消失了。

更新:现在你已经更新了问题......

我个人认为将onMouseMove以及_onMouseMove作为对象的一部分暴露并没有多大价值。我已经看到一些这样编写的javascript库基于一些假设,即人们将“遵守约定”并将以_为前缀的属性视为私有。

也许,我会做这样的事情:

var Main = function(){
   var _onMouseMove = function(event){ ... do stuff...};
   return {
       enable: function(){...},
       onMouseMove: _onMouseMove
   }
}

答案 2 :(得分:1)

不,这不是任何优化(至少据我所知)。

我对chrome扩展没有太多了解,有时只读一些代码,没什么大不了的。但正如Brightgarden所说,你所询问的模式是保护实施。在其他语言中,您有内置的机制来封装私有数据。不是在js。这大致,非常粗略,在我看来是一种模块模式 - 其中的例子已经在brightgarden的答案中给出。您可以在此处阅读有关js中实现的设计模式的更多信息:http://addyosmani.com/resources/essentialjsdesignpatterns/book/

具体来说:http://addyosmani.com/resources/essentialjsdesignpatterns/book/#modulepatternjavascript 对于模块模式

实际模块模式比您的示例更好,更少混淆。

答案 3 :(得分:0)

除了让读者感到困惑之外,“模式”没有任何好处。