Inheritance with Knockout.js

2019-02-26 15:34发布

I have some code like this:

var A = function(a,b,c) {
  var self = this;
  self.a = ko.observable(a);
  ... 


  self.function1 = ko.computed(function () {
      dothing(a);
      ...
  } 

  self.function2 = ko.computed(function () {
      dothing(b);
      ...
  }
}

var B = function(a,b,c,d) {
    var self = this;
  self.a = ko.observable(a);
  ... 


  self.function1 = ko.computed(function () {
      dothing(a);
      ...
  } 

  self.function2 = ko.computed(function () {
      dothing(b);
      ...
  }
}

How can I "extract" function1 and function2 to a function that A and B can share?

4条回答
甜甜的少女心
2楼-- · 2019-02-26 16:22

That's just where prototypes fit in:

function AB()
{};//empty object
AB.prototype.function1 = function()
{
    var self = this;//doesn't have access to self, but `this` will point to either A or B
    //do stuff
};
var A = function()
{
    var self = this;//constructor
}
var B = function()
{
    var self = this;//constructor
}
A.prototype = new AB;
A.prototype.constructor = A;
B.prototype = new AB;
B.prototype.constructor = B;
//marginally shorter:
A.prototype = B.prototype = new AB;
A.prototype.constructor = A;
B.prototype.constructor = B;
//instances:
var foo = new A();
var bar = new B();
console.log(foo.function1 === bar.function1);//logs true

Having said that, personally, I prefer to define my constructors regularly:

function A()
{
    var self = this;
}
foo = new A();
console.log(Object.getPrototypeOf(foo).constructor.name);//logs A

Whereas your code assigns an anonymous function to a variable, which means that the constructor doesn't have a name:

foo = new A();
console.log(Object.getPrototypeOf(foo).constructor.name);//logs ''

It's not that big of a deal, but just so you know...


Reference a method from the global (or any other) scope:

var virtualNewFunction = new A();//create object
virtualNewFunction = virtualNewFunction.function1;//virtualNewFunction now references function1
virtualNewFunction();

The closure will be accessible (exposed), still, but be very careful with this:

A = function()
{
    var self = this;
    this.function1 = function()
    {
        console.log(this);
        console.log(self);
    };
}
foo = new A();
foo.function1();//logs A twice
foo = foo.function1
foo();//logs this -> window! self => A

An other possibility is "borrowing" a function:

A = function()
{
    var self = this;
    this.function1 = function()
    {
        console.log(this);
        console.log(self);
    };
}
B = function()
{//no method
    var self = this;
}
foo = new A();
bar = new B();
foo.function1.apply(bar,[]);//call as though function1 was method of B

Again, be careful: in this case this logs B, but self still references A! You could build in certain "safety nets":

    this.function1 = function()
    {
        self = this !== window && this !== self ? this : self;//redefine self to current caller object, unless it's window 
        console.log(this);
        console.log(self);
    };

But honestly, you might do well reading up on the this operator to grasp all this referencing trickery. It's not that hard once you get the basics. Also check the call and apply methods for more details on how to "share/borrow" methods

查看更多
聊天终结者
3楼-- · 2019-02-26 16:22

You could change the scope of the function by pulling it out of that object.

var function1 = function() {

}

var function2 = function() {

}

var A = function(a,b,c) {
  var self = this;
  self.a = ko.observable(a);
  ... 


  self.function1 = ko.computed(function1)

  self.function2 = ko.computed(function2)
}
查看更多
够拽才男人
4楼-- · 2019-02-26 16:29
    var AB=function(){
    self=this;
    self.function1=function(){
                   //----something------
                  }
    self.function1=function(){
                   //----something------
                  }

   }


     var A=function(){
     var self=this;
     AB.apply(self,arguments);
     } 

    var B=function(){
     var self=this;
     AB.apply(self,arguments);
        } 
查看更多
欢心
5楼-- · 2019-02-26 16:38

You could try using the underscore.js extend functionality to do the inheritance.

查看更多
登录 后发表回答