2011-06-20 121 views
7

比方说,我有一个JavaScript对象:设置length属性

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

我可以用它像这样:

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

我试图让.length不是一个函数,所以我可以像这样访问它:x.length,但我没有得到这个工作的运气。

我想这一点,但它输出0,因为这是的A在时间长度:

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

我也试过这样,它也输出0

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

怎么办我得到x.length以输出对象内部数组的正确长度?

+1

下面是关于[试图继承阵列(http://perfectionkills.com/how-ecmascript-5-still-does-not-allow-to-subclass-an-array/)一些有趣的阅读。 – Pointy

回答

2

因为当你调用a.length,你返回的功能。为了返回输出,你必须实际调用该函数,即:a.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; 
    }; 
}; 
+0

这是一个有效的答案,只不过你修改了'.remove()'方法的返回值(不是你的答案中有任何设计缺陷)。 – JAAulde

+0

@JAAulde谢谢,当我写我自己的时候,我必须补充说。更新为与Rocket的原始问题类似。 – scurker

3

如果你想A保持'私人',你需要更新公共length财产的每一个操作,修改A的长度,这样你就不需要一个方法,检查时问。我会通过'私人'方法来做到这一点。

代码:

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; 
    }; 
}; 

演示: http://jsfiddle.net/JAAulde/VT4bb/

0

我不认为你可以访问它作为一个变量,我颇有基础的变量不能返回方法的值,除非你会劫持数组对象,并在push/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(); 
    }; 
}; 
+0

我目前的'方法'版本正常工作。 'A'在它前面没有'this.',因为这使得它成为函数的'私人'成员。 –

+0

啊,我的不好。我错过了这个变种。谢谢你让我知道。 – joostschouten

5

您可以使用valueOf hack

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

现在,您可以访问长度x.length。 (虽然也许只是我,但对我来说,关于这个方法的东西感觉非常迂回,并且很容易用更坚固的解决方案去做,例如,在每次修改后更新length属性。)

+0

比我快,最佳答案... + 1! –

+0

这是一个很不好的做法。我喜欢。 –

1

尽管每个人都说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 

你应该使用Object.create,而不是功能的,虽然我已经离开它作为一个功能,看起来像你的原件。

+0

酷,这个工程(在Chrome 13中)。不知道'get length()'语法。 –

+1

它适用于很多浏览器:Chrome 12,FF4。虽然尚未在IE中实现。 – davin

-1
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

谢谢,但这个问题已经解决了。 –