javascript different OOP methods standards

2019-09-04 02:11发布

For the longest time i have been doing JavaScript classes by doing the following

function MyClass(){
    this.v1;
    this.foo = function(){
        return true;
    }
};

Then i found TypeScript and it looks like it compile its Classes down to

var MyClass = (function () {
    function MyClass(message) {
        this.v1 = message;
    }
    MyClass.prototype.foo = function () {
        return "Hello, " + this.v1;
    };
    return MyClass;
})();

Another Method i have found a lot on the web is

var MyClass = {
    v1:1,
    foo: function(){
       return true;
    }
};

This looks ugly to me but maybe i'm missing something beneficial with this method, as it looks to be the way most people on the web do objects in javaScript.

The first method i'm able to do inharitance from a function i made.

Function.prototype.extends = function(parent){
    this.prototype = new parent();
    this.prototype.constructor = this;
};

I have also seen many other methods on making classes in JavaScript. I would like to know if my method is wrong or if there is a best practice method in doing OOP. All of my projects I have done use the first example. You can see on https://github.com/Patrick-W-McMahon now that I see what JavaScript compilers are doing i'm starting to question my methods. I would like to know what other JavaScript programmers advise is the best method and if there is a difference between the methods. I came from a C++/Java background and as such I write my JavaScript to match my background.

3条回答
等我变得足够好
2楼-- · 2019-09-04 02:36

What you read here is called the power constructor, more about it here:

Douglas Crockford about Inheritance


As a multi-paradigm language JavaScript lends itself very well to these different considerations. The truth is, it molds around your brain the way you can conceive it.

In other words, if you can reason about your structure in one way, than use it that way.

If you, on the other hand, want to be completely "free" of your own constraints, then you should abandon reasoning in classes altogether and embrace prototypal inheritance without any thing that resembles a class at all. Duck typing is then a natural consequence and in the extreme you'd use closures all over the place.

What I often do is this:

function myItemBuilder(p1)
{
  var s0, p0 = 0;

  // s0 is a shared private property (much like static in classes)
  // p0 is a shared private property but will be factorized (rendered non-shared)
  // p1 is a private instance property

  return (function (p0) { // factorize p0 if necessary

    return {
      publicProperty : 3,
      method1 : function (arg1) {
        // code here (may use publicProperty, arg1, s0, p0 (factorized) and p1)
      },
      method2 : function (arg2) {
        // code here (may use publicProperty, arg2, s0, p0 (factorized) and p1)
      }
    };
  }(p0++)); // on each invocation p0 will be different and method1/method2 will not interfere across invocations (while s0 is shared across invocations)
}

EDIT: The internal closure is only required if you need to factorize p0 (i.e. have separate, independent values for p0 on each invocation). Of course, if you don't need p0 factorized omit the internal closure.

The above example is intentionally more complex than required to illustrate various interesting cases.

Invoking this method like myItemBuilder("hello") builds a new item that has those specific features but there really is no class construct per se.

This is an especially powerful way of getting instances when you want to abandon classical inheritance. For example in C++ you can inherit from more than one class, which is called a mix-in. In Java and C# you only have single-inheritance but interfaces come to your help.

Here, what I've shown above, is the assembly line metaphor which can assemble components into an instance, with the result that there is no concrete (1) difference between class, interface and mix-in. They are all just instances that have features you can reflect upon through meta-programming (duck typing, reflection/inspection). There still is a logical (2) difference in that: (1) concrete instances behave the same independently of the way they come to being but (2) logically an interface is a contract while an instance is an implementation.

If you really understand SOLID and the Assembly Line Metaphor all of this makes sense. Otherwise I beg your pardon for this long answer :)

ADDED:

With this approach you can't check types, but you don't need to because duck typing allows you to find the method you need without having to look at a class or interface contract. This is similar to having each method in a separate single-method interface.

查看更多
不美不萌又怎样
3楼-- · 2019-09-04 02:54

its a matter of personal preference. Using this method

var MyClass = {
    v1:1,
    foo: function(){
       return true;
    }
};

results in fewer characters and thus smaller JS files so it is the method I usually go with but there is no wrong or right way. Btw. since you commented about this sort of object construction to be ugly you may want to stick with what you are used to. However if you are feeling adventurous check out this project.

It makes oop in javascript quick and painless and MUCH less ugly. Plus it supports multiple inheritance correctly.

查看更多
兄弟一词,经得起流年.
4楼-- · 2019-09-04 03:01

This is explained here

http://www.2ality.com/2011/06/coffeescript-classes.html

A normal JavaScript class definition, wrapped in an IIFE [3]. There is no benefit for using an IIFE here, apart from having a single assignment (which would matter in an object literal, but doesn’t here).

查看更多
登录 后发表回答