viewmodel中的viewmodel .prototype .function vs self .function?

How*_*utz 9 viewmodel knockout.js yeoman-generator

下面的两个代码块在上下文中工作,并且看起来完全在功能上等效.我理解js原型相当不错,所以我本身并不是在询问它们(除非这唯一的区别).

相反,比较两种简单的方法将方法放在视图模型上,如下所示,Knockout是否存在任何影响/差异,例如绑定时间?

define(["knockout","text!./ home.html"],function(ko,homeTemplate){// < - 一个AMD模块

    function HomeViewModel(route) { 
             var self = this; 
             self.message = ko.observable('Snacks!');

             self.eatSomething = function () { 
                  self.message('Yum, a viewmodel snack.'); 
             };   
    }
    return { viewModel: HomeViewModel, template: homeTemplate };
});
Run Code Online (Sandbox Code Playgroud)

与通过原型添加方法:

define(["knockout","text!./ home.html"],function(ko,homeTemplate){

    function HomeViewModel(route) {  
             this.message = ko.observable('Snacks!'); 
    };   

    HomeViewModel.prototype.eatSomething = function () { 
             this.message('Yum, the same viewmodel snack, only different?'); 
    };  
    return { viewModel: HomeViewModel, template: homeTemplate }; 
Run Code Online (Sandbox Code Playgroud)

});

(代码是通过Knockout生成器Yeoman脚手架输出的简单模型.它创建了一个淘汰组件的锅炉板代码,一个相当新的(KO 3.2)和非常受欢迎的功能.一个不错的KO组件解释器就在这里.)

RP *_*yer 13

在第一个例子中,由于函数使用self(设置为对新实例的引用)而不是this无论函数如何被调用/绑定,它总是正确地设置它自己的message可观察对象.

在第二个例子中,当正常绑定到函数时data-bind="click: eatSomething",你会得到相同的结果.Knockout使用this等于当前数据的值调用函数.

如果您有一个需要从不同的上下文调用该函数的场景(可能您的视图模型具有您正在使用的子对象with或模板).然后你可能会使用类似的绑定data-bind="click: $parent.eatSomething".KO仍会将该函数调用为this等于当前数据(这不会是$parent),因此您会遇到问题.

将函数放在原型上的一个优点是,如果你创建了许多实例,HomeViewModel它们将eatSomething通过原型共享相同的函数,而不是每个实例都获得它自己的eatSomething函数副本.在您的方案中,这可能不是一个问题,因为您可能只有一个HomeViewModel.

您可以通过调用它来确保上下文正确:data-bind="click: $parent.eatSomething.bind($parent).使用此调用,将创建一个新的包装函数,该函数使用适当的上下文(值this)调用原始函数.或者,您也可以在视图模型中绑定它以保持绑定更清晰.无论哪种方式,你确实失去了将它放在原型上的一些价值,因为你正在为每个实例创建包装函数.该功能的"胆量"至少只会在原型上存在一次.

我倾向于在我的代码中使用原型,但毫无疑问,使用该self技术(或类似于揭示模块模式)可以减少您对值的关注this.