What techniques can be used to define a class in JavaScript, and what are their trade-offs?

后端 未结 19 1490
庸人自扰
庸人自扰 2020-11-22 07:26

I prefer to use OOP in large scale projects like the one I\'m working on right now. I need to create several classes in JavaScript but, if I\'m not mistaken, there are at le

19条回答
  •  栀梦
    栀梦 (楼主)
    2020-11-22 08:03

    I prefer to use Daniel X. Moore's {SUPER: SYSTEM}. This is a discipline that provides benefits such as true instance variables, trait based inheritance, class hierarchies and configuration options. The example below illustrates the use of true instance variables, which I believe is the biggest advantage. If you don't need instance variables and are happy with only public or private variables then there are probably simpler systems.

    function Person(I) {
      I = I || {};
    
      Object.reverseMerge(I, {
        name: "McLovin",
        age: 25,
        homeState: "Hawaii"
      });
    
      return {
        introduce: function() {
          return "Hi I'm " + I.name + " and I'm " + I.age;
        }
      };
    }
    
    var fogel = Person({
      age: "old enough"
    });
    fogel.introduce(); // "Hi I'm McLovin and I'm old enough"
    

    Wow, that's not really very useful on it's own, but take a look at adding a subclass:

    function Ninja(I) {
      I = I || {};
    
      Object.reverseMerge(I, {
        belt: "black"
      });
    
      // Ninja is a subclass of person
      return Object.extend(Person(I), {
        greetChallenger: function() {
          return "In all my " + I.age + " years as a ninja, I've never met a challenger as worthy as you...";
        }
      });
    }
    
    var resig = Ninja({name: "John Resig"});
    
    resig.introduce(); // "Hi I'm John Resig and I'm 25"
    

    Another advantage is the ability to have modules and trait based inheritance.

    // The Bindable module
    function Bindable() {
    
      var eventCallbacks = {};
    
      return {
        bind: function(event, callback) {
          eventCallbacks[event] = eventCallbacks[event] || [];
    
          eventCallbacks[event].push(callback);
        },
    
        trigger: function(event) {
          var callbacks = eventCallbacks[event];
    
          if(callbacks && callbacks.length) {
            var self = this;
            callbacks.forEach(function(callback) {
              callback(self);
            });
          }
        },
      };
    }
    

    An example of having the person class include the bindable module.

    function Person(I) {
      I = I || {};
    
      Object.reverseMerge(I, {
        name: "McLovin",
        age: 25,
        homeState: "Hawaii"
      });
    
      var self = {
        introduce: function() {
          return "Hi I'm " + I.name + " and I'm " + I.age;
        }
      };
    
      // Including the Bindable module
      Object.extend(self, Bindable());
    
      return self;
    }
    
    var person = Person();
    person.bind("eat", function() {
      alert(person.introduce() + " and I'm eating!");
    });
    
    person.trigger("eat"); // Blasts the alert!
    

    Disclosure: I am Daniel X. Moore and this is my {SUPER: SYSTEM}. It is the best way to define a class in JavaScript.

提交回复
热议问题