0

I have a constructor:

function Point(point, left, right) {
    this.p = point;
    this.l = left;
    this.r = right
}
var bezierPoint = new Point([0.0,0.0],[-50.43794, 0.0],[25.54714,4.78643])

Is there a proper way to make a method that I could use among all the properties and not with the object itself? For example if I want to output

console.log(bezierPoint.l) // -50.43794, 0.0
console.log(bezierPoint.l.round()) // -50, 0
console.log(bezierPoint.r.round()) // 26, 5

Or is this the wrong approach and I should make new methods for the types of data I'll be working with? Something like

Array.prototype.round = function() {
    return [Math.round(this[0]), Math.round(this[1])] //this code doesn't matter now
}
console.log(bezierPoint.l.round()) // -50, 0
5
  • Is there a reason why you don't want to use prototype? Commented Oct 12, 2015 at 13:02
  • As bezierPoint.l seems to return an array, the only way to get what you want is to add to the Array constructor, which you probably shouldn't Commented Oct 12, 2015 at 13:02
  • I prefer that you change the protoype of point rather than Array's prototype. Commented Oct 12, 2015 at 13:02
  • Avoid patching the Array prototype. Maybe look to add those methods to your Point constructor. An example could be Point.getRounded that would return a rounded top, left and right. bezierPoint.getRounded to return [0,0], [-50, 0], [26, 5]. Commented Oct 12, 2015 at 13:08
  • So if I understand correctly, it'd be better to add a method for Point, that will do what I need with supplied property? Something like bezierPoint.getRounded(p) instead of 'bezierPoint.p.getRounded()' Commented Oct 12, 2015 at 16:29

2 Answers 2

1

You can use the parameters as inner variables and expose the methods as follows:

function Point(point, left, right) {

    function exposed(points) {
        return {
            value: function () {
                return points;
            },
            round: function () {
                return [Math.round(points[0]), Math.round(points[1])];
            }
        };
    }

    this.p = exposed(point);

    this.l = exposed(left);

    this.r = exposed(right);

}

Then you can use it like:

var bezierPoint = new Point([0.0, 0.0], [-50.43794, 0.0], [25.54714, 4.78643]);

document.write('value:' + bezierPoint.l.value() + '<br />'); // value:-50.43794,0

document.write('round:' + bezierPoint.l.round() + '<br />'); // round:-50,0
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for reply, so if I want 3 same methods for every property (.p, .l and .r) I'll have to declare 3 same looking functions?
I´ve edited the answer so you can use one generic function to expose all the methods you want. However keep in mind that this is just one of the possible ways of doing it, @paul's solution works just as fine.
1

Yet another approach. A bit more code, but more prototypical and solid.

// Common point class

/**
 * Creates simple point class
 * Point can be passed as two separate coordinates or as an array (coordinates pair). In case of array, second argument is omitted.
 * @param {String|Number|Array} a
 * @param {String|Number|undefined} b
 * @returns {Point}
 */
var Point = function (a, b) {
    if (!!a && !!b) {
        this.a = parseFloat(a);
        this.b = parseFloat(b);
    } else if (a.constructor === Array ? a.length === 2 : false) {
        this.a = parseFloat(a[0]);
        this.b = parseFloat(a[1]);
    } else {
        throw 'Wrong data provided for `Point`';
    }
}

/**
 * @returns {Array} Rounded coordinates pair
 */
Point.prototype.round = function () {
    return [Math.round(this.a), Math.round(this.b)];
}

/**
 * @returns {Array} Raw coordinates pair (as they were passed to constructor)
 */
Point.prototype.value = function () {
    return [this.a, this.b];
}

// Bezier point class

/**
 * Creates a Bezier point instance
 * @param {Array|Point} point
 * @param {Array|Point} left
 * @param {Array|Point} right
 * @returns {BezierPoint}
 */
var BezierPoint = function (point, left, right) {
    this.p = point instanceof Point ? point : new Point(point);
    this.l = left instanceof Point ? left : new Point(left);
    this.r = right instanceof Point ? right : new Point(right);
}

// Operation

var bezierPoint = new BezierPoint([0.0,0.0], [-50.43794, 0.0], [25.54714,4.78643]);

Each point can be passed to BezierPoint as an array or already well-formed Point class.


UPD: As an extension for existing answer ability to define arbitrary number of points can be provided next way.

var ArbitraryNumberOfPoints = function (args) {
    this.points = args.length === 0 ? [] :
        args.map(function (arg) {
            return arg instanceof Point ? arg : new Point(arg);
        });
}

ArbitraryNumberOfPoints.prototype.round = function () {
    return this.points.map(function (pointInstance) {
        return pointInstance.round();
    });
}   

2 Comments

But this way I'm getting only 2 coordinates per object, am I? I wanted to have all 6 coordinates in one Point object (2 coordinates of the point itself + 2 coordinates of 2 control points) and use round() method on them, not on the object itself
Here is the point you can start with. To make round more dynamic, you can use Array.prototype.map(). To make points more extensive, you can use array for storing pints (not assigning each point to separate variable in class) and than apply round through map on each Point in this array.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.