使用ES6 getter和setter而不是getProperty / setProperty约定的理由是什么?

时间:2015-08-20 09:26:20

标签: javascript ecmascript-6

class Foo {
    getName = () => this.name;

    setName = (name) => this.name = name;
}

class Foo {
    get name () {
        return this.name;
    }

    set name (name) {
        this.name = name;
    }
}

我可以想到 ES6 getter处于劣势的几个例子,例如

您无法编写将根据参数值返回值的getter:

/**
 * Returns an instance of Card associated with an element.
 *
 * @param {HTMLElement} element
 * @return {Card|undefined}
 */
getCard = (element) => {
    return _.find(this.index, {
        element: element
    });
};

没关系,但如果你使用这个和ES6,你就会引入代码风格的不一致。

您无法区分直接属性访问和方法访问。

class Foo {
    get name () {
        return this.name;
    }

    get expensive () {
        // An operation that takes a lot of computational power.
    }

    get randomValue () {
        // Returns random value.
    }
}

let foo = Foo();

foo.name;
foo.expensive;
foo.randomValue;

缺点是,您访问的属性可能需要大量计算能力(因此应该被记忆)或者每次访问它时都会发生变化,这是不直观的。

最后,getter / setter不能与arrow functions一起使用。示例无效:

class Foo {
    get name = () => {
        return this.name;
    }

    set name = (name) => {
        this.name = name;
    }
}

这使他们暴露于背景问题。

与传统的get{PropertyName}set{PropertyName}抽象相比,使用ES6 getter和setter 的优势是什么?

2 个答案:

答案 0 :(得分:11)

  

您无法区分直接属性访问和方法访问。

这是对他们有利的主要论据。

编写经典的Java风格的OO代码最奇怪的痛苦之一是,任何具有暴露属性的对象都必须编写getter和setter,并且大量的样板文件正在逐步推出,特别是对于大型数据结构类型对象(例如DTOs)。

所有这些的原因是你不能公开属性,否则你无法在不破坏API的情况下为它们添加逻辑(例如逻辑只允许设置某些值,或者以稍微不同的方式重构和存储属性,同时仍然暴露相同的外部API或类似的)。有关此问题的一些典型论据,请参阅https://softwareengineering.stackexchange.com/questions/176876/why-shouldnt-i-be-using-public-variables-in-my-java-class

我认为你可以轻松地说近年来这已经达到了它的逻辑极端,但这并不意味着它是错的;通过公开直接访问的公共字段,您确实暴露了您存储该数据的内部实现,这意味着您无法再轻松或安全地更改它。

ES6 getter / setters解决了这个问题。某些东西作为对象的直接属性可读的事实不再告诉您有关该属性的实现的任何信息。它最初可能是一个字段,但最近变成了ES6属性访问器,而没有更改API。该属性的实现对代码库的其余部分是隐藏的,因此更容易更改。

  

缺点是,您访问的属性可能需要大量计算能力(因此应该被记忆)或者每次访问它时都会发生变化,这是不直观的。

你是对的,这是一种风险。这也是任何getX()的问题;这是一个强有力的惯例,暗示了很好的简单方法,比如' getName()'我不应该在幕后做昂贵的事情,即使它们是方法,如果你打破了,你几乎肯定最终会把人赶出去(包括你自己,6个月后)

迁移到属性并不会改变这一点,但是你说得对,ES6意味着你不再保证对简单的财产访问是安全的。答案实际上只是你必须确保你(以及其他所有人)坚持使用约定和Principle of Least Astonishment:就像现有的简单的getter和setter一样,ES6属性访问者应该做简单便宜的事情,并且不应该这样做。在别处有奇怪的副作用。

答案 1 :(得分:4)

无法getMethod()setMethod()执行任何具体操作,但它允许使用不同的代码样式。例如,您可以使用get fooset foo编写:

obj.foo++;

将调用getter然后调用setter。当然,您可以使用set函数验证该值是否在特定范围内。传统的代码看起来像:

obj.setFoo(obj.getFoo() + 1);
  

您无法区分直接属性访问和方法访问。

这有点重要。我认为,如果某些东西真的昂贵,你就不应该使用它来获取它。