Javascript OO syntax

2019-06-19 00:41发布

There seem to be many different ways of doing OO in JavaScript.

I like:

function ClassA(){};
ClassA.prototype={
    someFunc:function(a,b,c){},
    otherFunc:function(){}
}
var c=new ClassA();

and have never used features beyond what this provides (despite being a proficient OOer). I suspect this is old fashioned, because every so often I see new spangled variants, and it makes me wonder if I'm choosing the best approach. For instance, you can do magic in the constructor method to create private variables and accessor methods, something I believed (until relatively recently) to be impossible. What about subclassing? I wouldn't know how to achieve this, but it must have some sort of common pattern by now.

How do you do it and why?

7条回答
地球回转人心会变
2楼-- · 2019-06-19 01:18

Simple JavaScript Inheritance

Because John Resig said so.

查看更多
唯我独甜
3楼-- · 2019-06-19 01:22

OOP in Javascript for Canvas

Check out how useful OOP in js can be in a different situation... This lets you draw squares and circles as objects so that you can go back and loop over or manipulate them as you like.

function Shape(x,y,color){
  this.x = x
  this.y = y
  this.color = color
}

function Square(height,width,color){
  Shape.call(this, event.x, event.y, color)
  this.height = height
  this.width = width
  this.x -= canvas.offsetLeft + (this.height/2)
  this.y -= canvas.offsetTop + (this.width/2)
}

Square.prototype = new Shape();
Square.prototype.draw = function(color){
  ctx.fillStyle = color
  ctx.fillRect(this.x,this.y,this.height,this.width)
}

function Circle(color, width){
  Shape.call(this)
  this.x = event.x -60
  this.y = event.y -60
  this.width = width
 }

Circle.prototype = new Shape();
Circle.prototype.draw = function(color){
  ctx.beginPath()
  ctx.arc(this.x,this.y,this.width,0,2*Math.PI, false);
  ctx.fillStyle = color
  ctx.fill()
}
查看更多
何必那么认真
4楼-- · 2019-06-19 01:31
function foo() {
  var bar = function() { console.log("i'm a private method"); return 1; };
  var iAmAPrivateVariable = 1;

  return {
    publicMethod: function() { alert(iAmAPrivateVariable); },
    publicVariable: bar()
  }
}

//usage
var thing = foo()

This is known as a functional appoach, since you are actually leveraging closures for encapsulation (which is the only way to do it in javascript).

In a general way, you shouldn't be doing OO in javascript, it isn't that great a language for it for a great many reasons. Think scheme with squiggly brackets and semi-colons, and you will start writing the language like the pros do. That being said, sometime OO is a better fit. In those cases, the above is typically the best bet

EDIT: to bring inheritance into the mix

function parent() {
  return { parentVariable: 2 };
}

function foo() {
  var bar = function() { console.log("i'm a private method"); return 1; };
  var iAmAPrivateVariable = 1;

  me = parent();
  me.publicMethod = function() { alert(iAmAPrivateVariable); };
  me.publicVariable = bar();

  return me;
}

This makes things a tad more complected, but accomplishes the desired end result while still taking a functional approach to OO concepts (in this case, using decorator functions instead of real inheritance). What I like about the whole approach is we are still really treating objects the way they are intended to be in this kind of language -- a property bag you can attach stuff to at will.

EDIT2:

Just wanted to give credit where credit is due, this approach is a very slight simplification to what doug crockford suggests in Javascript: The Good Parts. If you want to take your js skills to the next level, I would highly suggest starting there. I don't think I have ever learned so much from such a small book.

Another note is this is wildly different then what you will see most of the time in most of the jobs you will ever work at, and often is very hard to explain a) what is going on, and b) why it is a good idea to coworkers.

查看更多
Juvenile、少年°
5楼-- · 2019-06-19 01:35

I think joose is a pretty cool way to do OOP in javascript
http://code.google.com/p/joose-js/

查看更多
Animai°情兽
6楼-- · 2019-06-19 01:36

Objects in JavaScript are unlike almost all the other high-profile languages. Instead of being class-based (like in Java, C++, PHP, etc etc), they are prototype-based. As such, the basic paradigm of object-oriented programming has to be considerably modified. People who can't or don't want to re-think this and insist on using class-based thinking have to build class-based logic in JavaScript or use code from someone else who has already built it.

查看更多
混吃等死
7楼-- · 2019-06-19 01:36

I like to do something like

// namespace "My"
var My = new function {

  // private methods
  /**
   * Create a unique empty function.
   * @return {Function} function(){}
   */
  function createFn () {return function(){}}

  /** A reusable empty function. */
  function emptyFn () {}

  /**
   * Clone an object
   * @param {Object}  obj     Object to clone
   * @return {Object}         Cloned object
   */
  function clone (obj) { emptyFn.prototype=obj; return new emptyFn() }

  // public methods
  /**
   * Merge two objects
   * @param {Object} dst        Destination object
   * @param {Object} src        Source object
   * @param {Object} [options]  Optional settings
   * @return {Object}           Destination object
   */
  this.merge = function (dst, src, options) {
    if (!options) options={};
    for (var p in src) if (src.hasOwnProperty(p)) {
      var isDef=dst.hasOwnProperty(p);
      if ((options.noPrivate && p.charAt(0)=='_') || 
          (options.soft && isDef) || 
          (options.update && !isDef)) continue;
      dst[p]=src[p]; 
    }
    return dst;
  }

  /**
   * Extend a constructor with a subtype
   * @param {Function} superCtor      Constructor of supertype
   * @param {Function} subCtor        Constructor of subtype
   * @param {Object} [options]        Optional settings
   * @return {Function}               Constructor of subtype
   */
  this.extend = function (superCtor, subCtor, options) {
    if (!subCtor) subCtor=createFn();
    if (!options) options={};
    if (!options.noStatic) this.merge(subCtor, superCtor, options); 
    var oldProto=subCtor.prototype;
    subCtor.prototype=clone(superCtor.prototype);
    this.merge(subCtor.prototype, oldProto);
    if (!options.noCtor) subCtor.prototype.constructor=subCtor; 
    return subCtor;
  }

}

And then something like...

// namespace "My.CoolApp"
My.CoolApp = new function(){

  // My.CoolApp.ClassA
  this.ClassA = new function(){

    // ClassA private static
    var count=0; 

    // ClassA constructor 
    function ClassA (arg1) {
      count++;
      this.someParam=arg1;
    }

    // ClassA public static
    My.merge(ClassA, { 
      create: function (arg1) {
        return new ClassA(arg1);
      }
    }

    // ClassA public
    My.merge(ClassA.prototype, {
      doStuff : function (arg1) {
        alert('Doing stuff with ' + arg1);
      },
      doOtherStuff : function (arg1) {
        alert('Doing other stuff with ' + arg1);
      }
    }

    return ClassA;
  }

  // My.CoolApp.ClassB
  this.ClassB = new function(){

    My.extend(My.CoolApp.ClassA, ClassB);
    // ClassB constructor
    function ClassB () {
      ClassA.apply(this, arguments);
    }

    return ClassB;
  }

}

...the clone function is the key to inheritance. In short:

  • Clone an object by making it the prototype of a throwaway function and calling the function with 'new'.
  • Clone the parent constructor's prototype, and set it the result as the prototype of the child class.
查看更多
登录 后发表回答