Javascript object literal, how to solve context?

2019-02-19 09:28发布

问题:

I would like to start organizing my code properly, so I want to use object literals. In the following case, I'm doing a pseudo class. I would like that init() could work as a constructor, but unfortunately, I'm not seeing how to set attributes based on object context.

    var car = {
    context : this,
    wheels : 0,
    color : '',
    speed : 0,
    init : (function(x){
        console.log(x);
        x.wheels = 4;
        x.color = 'red';
        x.speed = 120;
    })(context)
};

console.log(car.color);

回答1:

You can't immediately run a function like that whilst declaring an object literal. What you can do:

var car = {
init : function(wheels,color,speed){
    this.wheels = wheels || 0;
    this.color = color || '';
    this.speed = speed || 0;
    return this;
  }
}.init(4,'red',120);

alert(car.speed); //=>120

Which removes the need for:

context : this,
wheels : 0,
color : '',
speed : 0,

...and offers the possibility for:

var car = {
    init : function(wheels,color,speed){
      this.wheels = wheels || 0;
      this.color = color || '';
      this.speed = speed || 0;
      return this;
     }
    },
    redAndFast = car.init(4,'red',230),
    threeWheeler = car.init(3,'yellowstriped',110);

[edit] What was I thinking? If you want more instances of Car, you'll have to use a real constructor function instead of an object literal:

var Car = function(){
  return {
    init : function(wheels,color,speed){
            this.wheels = wheels || 0;
            this.color = color || '';
            this.speed = speed || 0;
            return this;
  }
 }
},
redAndFast = new Car().init(4,'red',230),
threeWheeler = new Car().init(3,'yellowstriped',110);

Which can be simplified to:

var Car = function(wheels,color,speed){
            this.wheels = wheels || 0;
            this.color = color || '';
            this.speed = speed || 0;
    },
    redAndFast = new Car(4,'red',230),
    threeWheeler = new Car(3,'yellowstriped',110);

Or if you wanted to cling on to some init like function:

var Car = (function(){
    function car(wheels,color,speed){
            this.wheels = wheels || 0;
            this.color = color || '';
            this.speed = speed || 0;
    }
    return {
        init: function(w,c,s){
            return new car(w,c,s);
        }
    };
 })(),
 redAndFast   = Car.init(4,'red',230),
 threeWheeler = Car.init(3,'yellowstriped',110);

But hey, what happened to my context? you may ask. Well, it turns out you didn't need it after all. Isn't javascript a beautiful and flexible language?



回答2:

var Car = function() {
    this.wheels = 4;
    this.color = 'red';
    this.speed = 120;
}

var car = new Car();

It's best to use normal constructors for these kind of tasks.



回答3:

Object literals work for singletons. If you want an instantiable object, you'll need to learn how js oop works and just use function objects.