0

Say I have a class

class Something {
  constructor(a, b) {
    this.a = a;
    this.b = b;
  }
}

How can I instantiate an object so that I only assign a value to b without assigning a value to a ?

e.g. something along the lines of:

let someObject = new Something(b : 10);

with the expected output:

log(someObject.a) // undefined
log(someObject.b) // 10 

I want to avoid let someObject = new Something(undefined, 10); if I can for code readability reasons.

I'm kinda new to js, and I'm not really sure if this is even possible, but any help or guidance would be greatly appreciated!

nashpatty
  • 23
  • 3
  • 1
    Passing `undefined` appears to be exactly what you'd want here. – Bergi Apr 15 '20 at 21:40
  • 1
    Not tested, but here's an idea: pass the constructor an object instead (`constructor(values)`) and assign them so: `this.a = values.a;`, etc. You could then do `let someObject = new Something({b : 10});`. I mean, using `undefined` seems reasonable to me but if this object approach works best for you, great. – chriskirknielsen Apr 15 '20 at 21:42
  • There is no named parameter passing in JS. You can pass an object, with fields `a` and `b` if you want to simulate that, if you wish. – VLAZ Apr 15 '20 at 21:42
  • 1
    put a as second parametter, and set it a default value `constructor(b, a = 0) {...}`. Then you can create your instances with only one parameter: `const a = new Something(5);` – Reynier Rivero Apr 15 '20 at 21:45
  • @chriskirknielsen this seems like the closest solution to what I need. maybe i should look into limiting the number of arguments in my constructor if I'm having to think about this in the first place. – nashpatty Apr 15 '20 at 21:46
  • Like @ReynierAlbertoRiveroAlarcón shows as far as reversing the order of the arguments, without the second defaulting to `0`. Just leave that off. – StackSlave Apr 15 '20 at 21:47
  • @ReynierAlbertoRiveroAlarcón my use case was that I have a constructor as `constructor (a, b, c, d) {...} `. some objects may need to be instantiated as `new object(1, undefined, 3, 4) ` and others as `new object(1, 2, undefined, 4)` etc. so i thought maybe if i could explicitly state the key value pairs during instantiation it would make the code more readable. – nashpatty Apr 15 '20 at 21:50
  • @nashpatty just pass an object and destructure it, so you can call `new Something({a: 1, d: 4, c:3})` and your definition can just be `constructor({a, b, c, d})` – VLAZ Apr 15 '20 at 21:54
  • @VLAZ yes, thank you! I opted for passing object as a param – nashpatty Apr 15 '20 at 21:55
  • @nashpatty, after my post I'm reading your comment. I'm seeing you should just use a `method` *(function that is a property of a constructor)*. – StackSlave Apr 15 '20 at 22:00

1 Answers1

0

You can do like:

class Something{
  // private properties don't even work in Firefox and the syntax is just more typing than constructors
  constructor(b, a){
    this.a = a;
    this.b = b;
  }
}
const something = new Something(10);
console.log(something);

But I would do:

function Something(b, a){
  let see = 'Wow these private varibles are really easy to use in costructors! Classes are lame!';
  this.a = a; this.b = b;
}
const something = new Something(10);
console.log(something);

After reading your comment:

function Something(){
  this.objects = [].slice.call(arguments);
  this.getObjIndex = obj=>{
    return this.objects.indexOf(obj);
  }
  this.getObjByIndex = index=>{
    return this.objects[index];
  }
}
const objTest1 = {test:1}, objTest2 = {test:2}, objTest3 = {really:'cool', why:['a', 2, 'z']};
const something = new Something(objTest1, objTest3);
console.log(something.objects);
console.log(something.getObjIndex(objTest3));
console.log(something.getObjByIndex(0));

@VLAZ had so many comments (which I have no problem with, by the way) that I have to show about private variables:

function PrivateTest(){
  let test = 'cool';
  this.getTest = ()=>{
    return test;
  }
  this.setTest = mixed=>{
    test = mixed;
    return this;
  }
}
const pt = new PrivateTest;
console.log(pt.getTest());
console.log(pt.setTest('Look, VLAZ, it works!').getTest());
StackSlave
  • 10,613
  • 2
  • 18
  • 35
  • Why is the private property relevant? Also, the private variable does not have the same semantics at all as a private property. The latter will be more like `const Something = (function() { let private = "hidden but accessible in methods"; const constructor =function Something(){}; /* add methods */; return constructor; })();` – VLAZ Apr 15 '20 at 22:04
  • @VLAZ, I'm showing that `constructors` are actually easier to use than `class`es, which are really `functions` that actually do not introduce a new hierarchy. Firefox doesn't even support private properties. They're private so they wouldn't be inherited anyways. The example in your comment just throws a self-executing function around and returns the constructor. It's as if you never ran my code snippet. Bottom line: You're incorrect about the semantics... and the example in your comment is useless. – StackSlave Apr 15 '20 at 22:23
  • I ask again, why are private properties relevant? Your initial answer made a big point about them and you were the first person to mention private properties. I was pointing out that a private *variable* and a private *property* have different semantics - properties will be visible in methods, the private variable wouldn't. If you assign methods *inside* the constructor function, then you're really wasting the prototype and keeping a lot of functions in memory, instead of a single copy for each. – VLAZ Apr 15 '20 at 22:25
  • Sometimes I have like 30 private properties that I don't want showing up in a for in loop. If you make the variables private to the constructor, not the methods, the variable is available to all methods. – StackSlave Apr 15 '20 at 22:26
  • And how is that relevant to this question? – VLAZ Apr 15 '20 at 22:27
  • I'm just trying to help out. – StackSlave Apr 15 '20 at 22:28
  • By adding irrelevant information? I don't think that's helping. – VLAZ Apr 15 '20 at 22:29
  • Looks like you learned something. My job is done here! – StackSlave Apr 15 '20 at 22:31
  • Not really. Your justification for preferring "private properties" (that aren't properties) is quite weak, since you're forcing your object into bad shape to accommodate them. Your objects then have increased memory usage and are harder to extend and work with. Moreover, if you *just* don't want them to show up in a `for..in`, then you should have used `Object.defineProperty`/`Object.defineProperties` and pass `enumerable: false`. If you have 30 properties, you'd likely benefit from mixins and object composition, so it's all more reusable and easier to manage. I don't like your lesson. – VLAZ Apr 15 '20 at 22:38
  • Lexical scope of JavaScript makes it easy have access to other constructors without `extends`, which is the only part of the ES6 classes, that I did appreciate. – StackSlave Apr 15 '20 at 22:40