Constructors in JavaScript objects

后端 未结 19 1736
夕颜
夕颜 2020-11-22 10:21

Can JavaScript classes/objects have constructors? How are they created?

相关标签:
19条回答
  • 2020-11-22 10:38

    I found this tutorial very useful. This approach is used by most of jQuery plug-ins.

    http://www.htmlgoodies.com/html5/tutorials/create-an-object-oriented-javascript-class-constructor.html#fbid=OVYAQL_TDpK

    var Class = function(methods) {   
        var klass = function() {    
            this.initialize.apply(this, arguments);          
        };  
    
        for (var property in methods) { 
           klass.prototype[property] = methods[property];
        }
    
        if (!klass.prototype.initialize) klass.prototype.initialize = function(){};      
    
        return klass;    
    };
    

    Now ,

    var Person = Class({ 
        initialize: function(name, age) {
            this.name = name;
            this.age  = age;
        },
        toString: function() {
            return "My name is "+this.name+" and I am "+this.age+" years old.";
        }
    }); 
    
    var alice = new Person('Alice', 26);
    alert(alice.name); //displays "Alice"
    alert(alice.age); //displays "26"
    alert(alice.toString()); //displays "My name is Alice and I am 26 years old" in most browsers.
    //IE 8 and below display the Object's toString() instead! "[Object object]"
    
    0 讨论(0)
  • 2020-11-22 10:38

    Maybe it's gotten a little simpler, but below is what I've come up with now in 2017:

    class obj {
      constructor(in_shape, in_color){
        this.shape = in_shape;
        this.color = in_color;
      }
    
      getInfo(){
        return this.shape + ' and ' + this.color;
      }
      setShape(in_shape){
        this.shape = in_shape;
      }
      setColor(in_color){
        this.color = in_color;
      }
    }
    

    In using the class above, I have the following:

    var newobj = new obj('square', 'blue');
    
    //Here, we expect to see 'square and blue'
    console.log(newobj.getInfo()); 
    
    newobj.setColor('white');
    newobj.setShape('sphere');
    
    //Since we've set new color and shape, we expect the following: 'sphere and white'
    console.log(newobj.getInfo());
    

    As you can see, the constructor takes in two parameters, and we set the object's properties. We also alter the object's color and shape by using the setter functions, and prove that its change remained upon calling getInfo() after these changes.

    A bit late, but I hope this helps. I've tested this with a mocha unit-testing, and it's working well.

    0 讨论(0)
  • 2020-11-22 10:39

    Here's a template I sometimes use for OOP-similar behavior in JavaScript. As you can see, you can simulate private (both static and instance) members using closures. What new MyClass() will return is an object with only the properties assigned to the this object and in the prototype object of the "class."

    var MyClass = (function () {
        // private static
        var nextId = 1;
    
        // constructor
        var cls = function () {
            // private
            var id = nextId++;
            var name = 'Unknown';
    
            // public (this instance only)
            this.get_id = function () { return id; };
    
            this.get_name = function () { return name; };
            this.set_name = function (value) {
                if (typeof value != 'string')
                    throw 'Name must be a string';
                if (value.length < 2 || value.length > 20)
                    throw 'Name must be 2-20 characters long.';
                name = value;
            };
        };
    
        // public static
        cls.get_nextId = function () {
            return nextId;
        };
    
        // public (shared across instances)
        cls.prototype = {
            announce: function () {
                alert('Hi there! My id is ' + this.get_id() + ' and my name is "' + this.get_name() + '"!\r\n' +
                      'The next fellow\'s id will be ' + MyClass.get_nextId() + '!');
            }
        };
    
        return cls;
    })();
    

    I've been asked about inheritance using this pattern, so here goes:

    // It's a good idea to have a utility class to wire up inheritance.
    function inherit(cls, superCls) {
        // We use an intermediary empty constructor to create an
        // inheritance chain, because using the super class' constructor
        // might have side effects.
        var construct = function () {};
        construct.prototype = superCls.prototype;
        cls.prototype = new construct;
        cls.prototype.constructor = cls;
        cls.super = superCls;
    }
    
    var MyChildClass = (function () {
        // constructor
        var cls = function (surName) {
            // Call super constructor on this instance (any arguments
            // to the constructor would go after "this" in call(…)).
            this.constructor.super.call(this);
    
            // Shadowing instance properties is a little bit less
            // intuitive, but can be done:
            var getName = this.get_name;
    
            // public (this instance only)
            this.get_name = function () {
                return getName.call(this) + ' ' + surName;
            };
        };
        inherit(cls, MyClass); // <-- important!
    
        return cls;
    })();
    

    And an example to use it all:

    var bob = new MyClass();
    bob.set_name('Bob');
    bob.announce(); // id is 1, name shows as "Bob"
    
    var john = new MyChildClass('Doe');
    john.set_name('John');
    john.announce(); // id is 2, name shows as "John Doe"
    
    alert(john instanceof MyClass); // true
    

    As you can see, the classes correctly interact with each other (they share the static id from MyClass, the announce method uses the correct get_name method, etc.)

    One thing to note is the need to shadow instance properties. You can actually make the inherit function go through all instance properties (using hasOwnProperty) that are functions, and automagically add a super_<method name> property. This would let you call this.super_get_name() instead of storing it in a temporary value and calling it bound using call.

    For methods on the prototype you don't need to worry about the above though, if you want to access the super class' prototype methods, you can just call this.constructor.super.prototype.methodName. If you want to make it less verbose you can of course add convenience properties. :)

    0 讨论(0)
  • 2020-11-22 10:39

    It seems to me most of you are giving example of getters and setters not a constructor, ie http://en.wikipedia.org/wiki/Constructor_(object-oriented_programming).

    lunched-dan was closer but the example didn't work in jsFiddle.

    This example creates a private constructor function that only runs during the creation of the object.

    var color = 'black';
    
    function Box()
    {
       // private property
       var color = '';
    
       // private constructor 
       var __construct = function() {
           alert("Object Created.");
           color = 'green';
       }()
    
       // getter
       this.getColor = function() {
           return color;
       }
    
       // setter
       this.setColor = function(data) {
           color = data;
       }
    
    }
    
    var b = new Box();
    
    alert(b.getColor()); // should be green
    
    b.setColor('orange');
    
    alert(b.getColor()); // should be orange
    
    alert(color); // should be black
    

    If you wanted to assign public properties then the constructor could be defined as such:

    var color = 'black';
    
    function Box()
    {
       // public property
       this.color = '';
    
       // private constructor 
       var __construct = function(that) {
           alert("Object Created.");
           that.color = 'green';
       }(this)
    
       // getter
       this.getColor = function() {
           return this.color;
       }
    
       // setter
       this.setColor = function(color) {
           this.color = color;
       }
    
    }
    
    var b = new Box();
    
    alert(b.getColor()); // should be green
    
    b.setColor('orange'); 
    
    alert(b.getColor()); // should be orange
    
    alert(color); // should be black
    
    0 讨论(0)
  • 2020-11-22 10:41

    While using Blixt's great template from above, I found out that it doesn't work well with multi-level inheritance (MyGrandChildClass extending MyChildClass extending MyClass) – it cycles on calling first parent's constructor over and over. So here is a simple workaround – if you need multi-level inheritance, instead of using this.constructor.super.call(this, surName); use chainSuper(this).call(this, surName); with the chain function defined like this:

    function chainSuper(cls) {
      if (cls.__depth == undefined) cls.__depth = 1; else cls.__depth++;
      var depth = cls.__depth;
      var sup = cls.constructor.super;
      while (depth > 1) {
        if (sup.super != undefined) sup = sup.super;
        depth--;
      }
      return sup;
    }
    
    0 讨论(0)
  • 2020-11-22 10:43

    http://www.jsoops.net/ is quite good for oop in Js. If provide private, protected, public variable and function, and also Inheritance feature. Example Code:

    var ClassA = JsOops(function (pri, pro, pub)
    {// pri = private, pro = protected, pub = public
    
        pri.className = "I am A ";
    
        this.init = function (var1)// constructor
        {
            pri.className += var1;
        }
    
        pub.getData = function ()
        {
            return "ClassA(Top=" + pro.getClassName() + ", This=" + pri.getClassName()
            + ", ID=" + pro.getClassId() + ")";
        }
    
        pri.getClassName = function () { return pri.className; }
        pro.getClassName = function () { return pri.className; }
        pro.getClassId = function () { return 1; }
    });
    
    var newA = new ClassA("Class");
    
    //***Access public function
    console.log(typeof (newA.getData));
    // function
    console.log(newA.getData());
    // ClassA(Top=I am A Class, This=I am A Class, ID=1)
    
    //***You can not access constructor, private and protected function
    console.log(typeof (newA.init));            // undefined
    console.log(typeof (newA.className));       // undefined
    console.log(typeof (newA.pro));             // undefined
    console.log(typeof (newA.getClassName));    // undefined
    
    0 讨论(0)
提交回复
热议问题