Defining prototype methods inside the constructor
Asked Answered
W

2

9

Today, I saw a JavaScript pattern I have never seen in my whole life. I cannot tell the purpose of using this pattern. It seems wrong to me, but I want to be a little conservative. It might be some awesome pattern I never saw before.

function Dog() {
    Dog.prototype.bark = function () {
        alert('woof!');
    }

    this.bark = function () {
        Dog.prototype.bark();
    }

    this.bark();
}

First, I'm not a fan for making methods (as privileged members) inside the constructor for no reason. It would cause creating functions every time when an instance is created. Second, in this code snippet, it also calls the prototype name "Dog", instead of "this". This makes me super confused.

Anyone knows what good about it?

Thanks! Grace

Webster answered 19/8, 2011 at 0:4 Comment(2)
That seems extremely pointless. From what I know, the prototype object is used to add properties to all instances of an object outside the definition. Since that's in the definition, it's a bit redundant.Ronel
I totally agree with you. It seems pointless to me too.Webster
K
13

This is a very bad idea, for a great number of reasons. A few of which are:

  1. Adding methods to the prototype in the constructor will cause the prototype method to be replaced for all instances, everytime you instantiate a new Dog.
  2. Calling Dog.prototype.bark() means that this will be Dog.prototype and not your instance of Dog, which can cause serious issues.
  3. this.bark = function () { Dog.prototype.bark(); } is some serious WTF. Because this.bark will already evaluate to the prototype method making this unnecessary. And calling it like this actually destroys the natural this value, as mentioned in #2.

Here is what is should be:

function Dog() {
  this.makeSound();
};

Dog.prototype.bark = function() {
  alert('woof');
};

Dog.prototype.makeSound = function() {
  this.bark();
};

Or alternatively, without the prototype at all:

function Dog() {
  this.bark = function() {
    alert('woof');
  };

  this.makeSound = function() {
    this.bark();
  };

  this.makeSound();
};

I would not trust this snippet of yours at all.

Kotick answered 19/8, 2011 at 0:14 Comment(2)
#2: that is same even if bark is initialised outside the constructor - the method's this is set by the call. #3: the same as #2 (this will be Dog.prototype), but the function doesn't use this so it will not cause an issue in this case.Skald
Why would you make this.makeSound = function() { }? This example could be misleading without clarification. This doesn't get get set on the prototype object and the function is duplicated in memory for every instance of new Dog();. Better to Dog.prototype.makeSound = function () {}Expressive
R
3

Sorry for the VERY late reply, but if you really want to add the prototypes within the constructor AND not have it recreated whenever a new instance is created, you could do this:

function Dog() {
    if (!Dog.prototype.bark) {
        Dog.prototype = function() {
            console.log('woof');
        }
    }

    this.bark();
}

I still probably wouldn't use this method, but I have some across instances where this method was a option when dealing with 3rd party frameworks (the dodgy kind).

Rickrack answered 31/8, 2015 at 4:38 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.