1

I wrote aproximatley this code today:

function  Point  ()  {                   //  1
   var x,  y;                            //  2
                                         //  3
   this.setXY  =  function  (x,  y)  {   //  4
      x  =  x;                           //  5  doesn't  work
      y  =  y;                           //  6  doesn't  work
   }                                     //  7
}                                        //  8

I want to make setXY API look nice so I want to use x and y on line 4. However I also want to have my code internally nice, so I use x and y on line 2 for private variables.

Question I have is: Is is possible to have x and y everywhere in my code, both for private variables and function arguments? How would I assign x to x and y to y on line 5 and 6 so that it works?

bodacydo
  • 75,521
  • 93
  • 229
  • 319
  • 3
    is there a reason why you can't call the x,y parameters something else? Like, `x2` and `y2`? – kevin628 Jul 12 '15 at 04:05
  • YEs! like this - `this.setXY = function (X, Y) { ` – AdityaParab Jul 12 '15 at 04:14
  • @kevin628 That will make API ugly. I want to use `x` and `y` everywhere for nice internal (private part) code and also API (external API). – bodacydo Jul 12 '15 at 04:14
  • @Maverick interesting, capital X and Y for function arguments – bodacydo Jul 12 '15 at 04:15
  • Why not just use the argument versions of `x` and `y` Inside your function? What is the purpose of `x = y; y = y;`? – Cool Blue Jul 12 '15 at 04:28
  • @CoolBlue Purpose is to update x and y internal variables. See answer below by [AT]rampion. – bodacydo Jul 12 '15 at 04:31
  • 1
    `setXY` should be clear in and of itself. If another developer has a heart attack over the names of parameters, he or she is in the wrong profession. Don't write code to make APIs and documentation appear visually appealing; write code that is self-documenting to a reasonably intelligent developer. – kevin628 Jul 12 '15 at 04:55

2 Answers2

2

Within setXY, the function arguments x and y are shadowing the local variables x and y defined in the body of the Point function.

In javascript, there's no direct way to access a shadowed variable. By declaring your argument names to shadow the local variables, you've made the local variables inaccessible.

Commonly, instead of trying to access shadowed variables, javascript devs do one of two things in this situation:

  1. Use a different variable name:

    function Point() {
      var _x, _y;
      this.setXY = function(newX, newY) {
        _x = newX;
        _y = newY;
      };
    }
    p = new Point();
    p.setXY( 5, 7 );
    
  2. Store object-specific values in this rather than as local variables:

    function Point() {
      this.setXY = function(x, y) {
        this.x = x;
        this.y = y;
      };
    }
    p = new Point();
    p.setXY( 5, 7 );
    

The main difference between these two approaches is that

  1. Since they are local variables, _x and _y are inaccessible from outside of the definition of Point, so they can't be updated except via setXY.

  2. Since they are object members, this.x and this.y are accessible to anyone who has a reference to this, and can be modified outside of the definition of Point without using setXY. To continue the prior code:

    console.log( p.x, p.y ); // prints 5, 7
    p.x = 11;
    console.log( p.x, p.y ); // prints 11, 7
    
rampion
  • 87,131
  • 49
  • 199
  • 315
  • Thanks for detailed answer. I upvoted and will accept the answer in the next few days if there are no better answers. Your answer explains everything perfectly. Method 2 is dangerous for safe programming. Method 1 looks nice and I will go with it but instead of `_x` I will still use `x` internally and use `newX` for function arguments. Follow up question: What do you think of using `setXY(xx, yy)` - doubling variable names? I just came up with this scheme. Or `setName(namename)`. Or `split(sizesize)`. I think I like doubling variable names scheme even better than `newX`. – bodacydo Jul 12 '15 at 04:28
  • bodacydo: honestly, I think you're asking the wrong question. It looks like you want to use the same names for the arguments to avoid making "the API ugly". Users shouldn't be learning your API by reading your function definitions, they should be reading documentation. And if you have a tool that generates docs from your function definitions, why not ask how to make that tool use different names for the arguments? – rampion Jul 12 '15 at 04:34
  • In the first method, why not use `x` and `y` instead of `newX` and `newY` For the arguments? – Cool Blue Jul 12 '15 at 04:39
  • Cool Blue: to document intent – rampion Jul 12 '15 at 04:47
  • How do you document that? Are there any special documentation tools for javascript? I thought everyone read code to find api functions? – bodacydo Jul 12 '15 at 05:56
  • bodacydo: [generating javascript documentation](http://stackoverflow.com/questions/5841490/generating-javascript-documentation) – rampion Jul 12 '15 at 10:23
2

Short answer: no, it's not possible. By keeping the same names in your this.setXY method you are effectively overriding the parent scope's variables.

You seem to be allowing the raw x & y values to be modified - why not simply expose them and use your methods as utilities?

function Point (x, y) {
  this.x = x;
  this.y = y;

  // set X,Y in a single statement
  this.setXY = function (x, y) {
    this.x = x;
    this.y = y;
  }

  // utility example
  this.distance = function (x, y) {
    x = this.x - x;
    y = this.y - y;
    return Math.sqrt(x * x + y * y);
  }
}

Alternatively define an object to store your variables with the same name/key:

function Point (x, y) {

  // a private key store
  var point = {
    x: x || 0,
    y: y || 0
  };

  this.setXY = function (x, y) {
    point.x = x;
    point.y = y;
  }
}
som
  • 2,023
  • 30
  • 37
  • I like the alternative solution. I'm still using `x` and `y` in the code except through `point` object. – bodacydo Jul 12 '15 at 05:15
  • I like the second method too, though I wouldn't use it too often. You might also use a similar convention outside the function, eg. `var point = new Point();` – som Jul 13 '15 at 01:19
  • That's right, however if you are allowing the values to be set directly with your `setXY` method it shouldn't be a problem – som Jul 19 '15 at 10:13