是习惯用JS为简单属性编写getter吗?

时间:2011-10-09 16:04:08

标签: javascript coding-style

此代码是惯用的,还是应该直接访问属性?

self.isAlive = function() {
  return self.alive;
}

5 个答案:

答案 0 :(得分:2)

这完全取决于实施。

如果您觉得该物业总是价值,那么进入该物业就足够了。如果您觉得某些逻辑确定返回“格式正确”的值,我会使用一种方法(或者如果该值可能是基于其他因素的动态,那么方法是个好主意。)

更进一步,其他语言(如C#)具有可以安全地公开值的属性,但不一定会改变它们。 JS没有这样的保护方法,所以get<Var>通常用于公开属性,但是以只读方式。

一切都是关于对数据的喜好,同时也试图预测如果你通过一种方法直接暴露属性,最糟糕的情况可能是什么。

答案 1 :(得分:2)

您似乎在谈论经典OOP意义上的属性,即类的属性。在当前版本的Javascript中,模拟此行为并不完全干净。请考虑以下示例:

    var Widget = function() {
        var private = 'private';
    }

'Widget'是一个构造函数,'private'将在构造函数的范围内实例化。这意味着只有一种方法可以从构造函数范围之外访问'private':

    var Widget = function() {
        var private = 'private';
        this.getPrivate = function() {
            return private;
        }
    }

这将隐藏Widget的每个实例的私有变量,但不幸的是,现在必须将'getPrivate'添加到Widget的每个实例中。您可以通过语句this.getPrivate = ...在构造函数中看到这种情况。每次使用var widget1 = new Widget()创建Widget实例时,该特定实例都会添加一个新函数'getPrivate'。

在Javascript中制作可重用组件的常规方法是使用其原型继承的实现。您将原型对象分配给构造函数,该函数将在组件的所有实例中具有共享方法和属性。我将在下面提供一个示例来解释,但是如果您正在进行面向对象的javascript,那么您应该注意原型继承的警告。一个很棒的resource

以下是一个示例,说明如何为您的示例发挥作用:

    var Widget = function() {
        this.alive = true;
    }
    Widget.prototype.isAlive = function() {
        return this.alive;
    }
    var widget1 = new Widget();
    widget1.isAlive();  // returns true

这里的问题是属性alive正被添加到对象中,因此,它是公开可用的,即,您的Widget的任何用户都可以在他们最喜欢的FireBug变体中查看DOM并且看(以及自由修改)这个属性。

考虑一种变体,您尝试将alive隐藏到外部用户。由于aliveWidget个实例的属性,因此您需要包含代码以在构造函数中隐藏它,如下所示:

    var Widget = function() {
        var alive = true;
    }

但是,正如本文开头所述,在这种情况下alive仅暴露给构造函数的作用域;因此,原型上的方法无法访问。原因是每个方法都没有与构造函数相同的范围,因为Javascript只有函数范围。

总之,如果您尝试在可重用组件中隐藏数据,则javascript无法提供干净的方法。如果您不介意为每个组件实例分配相同方法的新内存,那么您可以在本文中使用我的第二个代码示例。但是,如果您希望仅在内存中分配方法一次,则需要在对象实例上公开属性,例如this.alive = true

答案 2 :(得分:1)

这是主观的。讨论了使用getter和setter的问题。有些人(像我一样)说你应该总是使用getter和setter来遵循封装原则,而有些人则说你不应该因为你的应用程序变得无法维护。

答案 3 :(得分:1)

如果您不希望外部js代码修改您的属性,这是一种很好的做法。如果这是期望的效果,您可以考虑使用var来分配该属性,而不是使其成为该对象的属性。这样,对象中的代码可以修改它,但只能通过getter访问

var alive = false;
function isAlive(){ return alive;}

答案 4 :(得分:1)

您可以使用:

function isAlive(){
    return arguments.callee.alive;
}
isAlive.alive=true;

在严格的模式下,这似乎还可以。

实现这一目标的另一种方法是

function isAlive(){
    return isAlive.alive;
}
isAlive.alive=true;

但问题是有人可以将名称用作字符串,或者重命名函数等等......你可以放弃状态。