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

What is the argument for using ES6 getters and setters over getProperty/setProperty convention?

本文关键字:约定 setProperty 理由 是什么 getProperty getter ES6 setter 使用      更新时间:2023-09-26
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不能用于箭头函数。无效的例子:

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

使它们暴露于上下文问题。

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

不能区分直接的属性访问和方法访问。

这是对他们有利的主要理由。

编写经典java风格的OO代码的最奇怪的痛苦之一是,任何具有公开属性的对象都必须编写getter和setter,并且由此产生了大量的样本文件,特别是对于大型数据结构类型的对象(例如dto)。

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

我认为你可以很轻松地说,近年来这种情况在逻辑上已经达到了极限,但这并不意味着它是错的;通过公开一个公共字段以供直接访问,你实际上是在公开如何存储该数据的内部实现,这意味着你不能再轻松或安全地更改它了。

ES6的getter/setter修复了这个问题。作为对象上的直接属性可读的事实不再告诉您有关该属性的实现的任何信息。它原本可以是一个字段,但最近变成了一个ES6属性访问器,没有更改API。该属性的实现对其他代码库是隐藏的,因此更容易更改。

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

你说得对,这是有风险的。这也是任何getX()的陷阱;有一种强烈的惯例表明,像'getName()'这样简单的方法不应该在后台做昂贵的事情,即使它们是方法,如果你打破了这个惯例,你几乎肯定会被人发现(包括你自己,6个月后)

移动到属性并没有改变这一点,但是你是对的,ES6意味着你不再保证简单的属性访问是安全的。答案是你必须确保你(和其他人)坚持惯例和最少意外原则:与现有的简单的getter和setter一样,ES6属性访问器应该做简单便宜的事情,并且不应该在其他地方有奇怪的副作用。

没有什么你不能getMethod()setMethod()做的事情,但是它允许不同的代码风格。例如,对于get fooset foo,可以这样写:

obj.foo++;

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

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

不能区分直接的属性访问和方法访问。

这就是问题的关键。我认为,如果某些东西真的昂贵,你就不应该为它使用getter。