开发者

Set length property of JavaScript object

Let's say I have a JavaScript object:

function a(){
    var A = [];
    this.length = function(){
        return A.length;
    };
    this.add = function(x){
        A.push(x);
    };
    this.remove = function(){
        return A.pop();
    };
};

I can use it like so:

var x = new a();
x.add(3);
x.add(4);
alert(x.length()); // 2
alert(x.remove()); // 4
alert(x.length()); // 1

I was trying to make .length not a function, so I could access it like this: x.length, but I've had no luck in getting this to work.

I tried this, but it outputs 0, because that's the length of A at the time:

function a(){
    var A = [];
    this.length = A.length;
    //rest of the function...
};

I also tried this, and it also outputs 0:

function a(){
    v开发者_Python百科ar A = [];
    this.length = function(){
        return A.length;
    }();
    //rest of the function...
};

How do I get x.length to output the correct length of the array inside in the object?


You could use the valueOf hack:

this.length = {
    'valueOf': function (){
        return A.length;
    },
    'toString': function (){
        return A.length;
    }
};

Now you can access the length as x.length. (Although, maybe it's just me, but to me, something about this method feels very roundabout, and it's easy enough to go with a sturdier solution and, for example, update the length property after every modification.)


If you want A to stay 'private', you need to update the public length property on every operation which modifies A's length so that you don't need a method which checks when asked. I would do so via 'private' method.

Code:

var a = function(){
    var instance, A, updateLength;

    instance = this;
    A = [];
    this.length = 0;

    updateLength = function()
    {
      instance.length = A.length;
    }

    this.add = function(x){
        A.push(x);
        updateLength();
    };

    this.remove = function(){
        var popped = A.pop();
        updateLength();

        return popped;
    };
};

Demo: http://jsfiddle.net/JAAulde/VT4bb/


Because when you call a.length, you're returning a function. In order to return the output you have to actually invoke the function, i.e.: a.length().

As an aside, if you don't want to have the length property be a function but the actual value, you will need to modify your object to return the property.

function a() {
  var A = [];
  this.length = 0;
  this.add = function(x) {
    A.push(x);
    this.length = A.length;
  };
  this.remove = function() {
    var removed = A.pop();
    this.length = A.length;
    return removed;
  };
};


While what everyone has said is true about ES3, that length must be a function (otherwise it's value will remain static, unless you hack it to be otherwise), you can have what you want in ES5 (try this in chrome for example):

function a(){
    var A = [],
        newA = {
         get length(){ return A.length;}
        };
    newA.add = function(x){
        A.push(x);
    };
    newA.remove = function(){
        return A.pop();
    };
    return newA;
}

var x = a();
x.add(3);
x.add(4);
alert(x.length); // 2
alert(x.remove()); // 4
alert(x.length); // 1

You should probably use Object.create instead of the function a, although I've left it as a function to look like your original.


I don't think you can access it as a variable as a variable to my knoledge cannot return the value of a method, unless you will hijack the array object and start hacking in an update of your variable when the push/pop methods are called (ugly!). In order to make your method version work I think you should do the following:

function a(){
    this.A = [];
    this.length = function(){
        return this.A.length;
    };
    this.add = function(x){
        this.A.push(x);
    };
    this.remove = function(){
        return this.A.pop();
    };
};


These days you can use defineProperty:

let x = {}

Object.defineProperty(x, 'length', {
  get() {
    return Object.keys(this).length
  },
})

x.length // 0
x.foo = 'bar'
x.length // 1

Or in your specific case:

Object.defineProperty(x, 'length', {
  get() {
    return A.length
  }
})


function a(){
    this.A = [];
    this.length = function(){
        return this.A.length;
    };
    this.add = function(x){
        this.A.push(x);
    };
    this.remove = function(){
        return this.A.pop();
    };
};
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜