简体   繁体   English

设置JavaScript对象的长度属性

[英]Set length property of JavaScript object

Let's say I have a JavaScript object: 假设我有一个JavaScript对象:

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. 我试图让.length不是一个函数,所以我可以这样访问它: x.length ,但我没有运气让它工作。

I tried this, but it outputs 0 , because that's the length of A at the time: 我试过这个,但它输出0 ,因为那是当时A的长度:

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

I also tried this, and it also outputs 0 : 我也尝试了这个,它也输出0

function a(){
    var 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? 如何让x.length在对象内部输出正确的数组长度?

You could use the valueOf hack : 你可以使用valueOf hack

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

Now you can access the length as x.length . 现在您可以访问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. 如果你希望A保持'私有',你需要更新每个修改A长度的操作的公共length属性,这样你就不需要一个在被问到时检查的方法。 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/ 演示: http //jsfiddle.net/JAAulde/VT4bb/

Because when you call a.length , you're returning a function. 因为当你调用a.length ,你正在返回一个函数。 In order to return the output you have to actually invoke the function, ie: a.length() . 为了返回输出,您必须实际调用该函数,即: 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. 顺便说一句,如果您不希望将length属性作为函数而是实际值,则需要修改对象以返回该属性。

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): 虽然每个人都说ES3是正确的,但是这个长度必须是一个函数(否则它的值将保持静态,除非你以其他方式破解它),你可以在ES5中拥有你想要的东西(例如在chrome中尝试这个):

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. 你可能应该使用Object.create而不是函数a,虽然我把它作为一个看起来像你原来的函数。

These days you can use defineProperty : 这些天你可以使用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
  }
})

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!). 我不认为你可以作为变量访问它作为变量我的知识无法返回方法的值,除非你将劫持数组对象并在调用push / pop方法时开始攻击变量的更新(丑陋!)。 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();
    };
};
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();
    };
};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM