3

When instance function are called in a class each instance of object get own copy of function but in prototype method and static method no copy is created , they belong to class, so if they both doesn't create a copy of their function, so why do we have static function if we can simply use prototype method if we don't want to copy??

I am a little bit confuse, if anyone can explain it will be a great help

  • In most OOP languages, instances do *not* get their own copy of functions. – Barmar May 20 '21 at 16:04
  • Instances are linked to the class object, and the class object contains the methods. – Barmar May 20 '21 at 16:06
  • 3
    A static method doesn't exist on instances. Prototype methods do. So, if you want to call `someArr.filter(x => x > 5)` that would be an instance method. But a static method would be `Array.isArray(someArr)`. It makes very little sense to make the static method an instance method because you'd need an instance before calling it. That would lead to stuff like `someArr.isArray(someArr)` which is illogical - you need an array to check if something is an array. And that can very easily be fail spectacularly if `someArr` is *not* in fact an array. – VLAZ May 20 '21 at 16:08
  • 1
    @VLAZ To be fair, you could use `[].isArray(someArr)` similar to the old idiom of `[].splice.call(someNonArray)` – Barmar May 20 '21 at 16:09
  • 2
    @Barmar true. I used the more illogical example to highlight why it's weird. Creating an object just to call a method on it that doesn't require the object to exist doesn't really make this design sensible. – VLAZ May 20 '21 at 16:10
  • See also [Why do some array methods rely on the global Array object?](https://stackoverflow.com/q/48957329/1048572) – Bergi Nov 23 '21 at 18:18

3 Answers3

4

In order to use a prototype/instance method, you need to either have an instance of an object or specifically access the type's .prototype. For methods that don't require an instance, a static method provides simpler syntax. Think of the String.fromCharCode() method as an example. It wouldn't make sense to say:

let str = "dummy string".fromCharCode(127);

The extra string instance there is just a distraction from what you're really trying to do:

let str = String.fromCharCode(127);

This applies good programming practices of reduced coupling (not requiring an instance in order to invoke a method that doesn't need it) and information hiding (by not exposing a method on instances of objects which doesn't pertain to those specific objects).

StriplingWarrior
  • 151,543
  • 27
  • 246
  • 315
2

A static method does not exist on instances. Prototype methods do. So, if you want to call someArr.filter(x => x > 5) that would be an instance method that works on the given array.

An example of astatic method is Array.isArray(someArr). It makes very little sense to make the static method an instance method because you'd need an instance before calling it. That would lead to code like someArr.isArray(someArr) which is illogical - you need an array to check if something is an array. And that can very easily be fail spectacularly if someArr is not in fact an array:

const someArr = { 
  isArray() { return true; },
  filter()  { return "I am not an array"; },
};


console.log(someArr.isArray(someArr));
console.log(someArr.filter(x => x > 5));

Yes, that example is indeed highly illogical in order to highlight why it is weird. Assuming .isArray() was an instance method, you could create a new array in order to use it to call [].isArray(someArr). But that method does not require any instance data. The object created exists only to give you access to the method and is discarded immediately afterwards. That design is still not sensible.

VLAZ
  • 26,331
  • 9
  • 49
  • 67
2

Both static methods and prototype methods exist independent from any instances. The difference is that a prototype method expects to be called on an instance, i.e. to have an instance passed as the this argument, whereas the static method does not require an instance and expects none.

Even without placing them anywhere on the class, we can see this distinction in the following example:

function myStaticMethod(arg) {
    console.log('Doing something with '+arg);
}
function myMethod(arg) {
    console.log('Doing something with '+this+' and '+arg);
}
const myInstance = new MyClass();

myStaticMethod('value');
myMethod.call(myInstance, 'value');

Now the .call() syntax is not very ergonomic, we prefer myInstance.myMethod('value'), so that is why we place the method on the prototype object of the class, having it inherited by all instances.

For static methods, this is not necessary. They don't need an instance, we don't want to call them on an instance, we want to call them as MyClass.myStaticMethod('value') so that is where we place them. We could put them on the prototype as well, but that would lead to confusion (myInstance.myStaticMethod()), name collisions, and unncessarily long invocations (MyClass.prototype.myStaticMethod()). It's imaginable to write new MyClass().myStaticMethod(), but there you would unnecessarily create an instance that is not required (and it might not even be possible to create).

Bergi
  • 630,263
  • 148
  • 957
  • 1,375