【问题标题】:What is the argument for using ES6 getters and setters over getProperty/setProperty convention?在 getProperty/setProperty 约定上使用 ES6 getter 和 setter 的论点是什么?
【发布时间】:2015-11-13 20:56:35
【问题描述】:
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
    });
};

没关系,但是,如果您使用 this 和 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 有什么优势

【问题讨论】:

  • 嗯,计算属性和设置时的类型/值检查肯定是有用的。如何实现它以及如何使用它取决于您。它是语法糖,不多也不少。您有责任负责任地使用它。
  • 这些都不是有效的ES6???请发布显示您实际在做什么的工作代码。
  • @GajusKuizinas:类属性(您的第一个示例)是 第 0 阶段 ES7 提案
  • 那你为什么说“ES6 getter and setter over getProperty/setProperty”*?那宁愿是class Foo { getFoo() { } } vs class Foo { get foo() {} }
  • @GajusKuizinas:这肯定会分散注意力。如果您的问题只是关于 getters(语法)与 getters(约定),那么这与 ES6+ 无关。 ES5 中引入了 Getter。

标签: javascript ecmascript-6


【解决方案1】:

getMethod()setMethod() 没有您不能做的任何特定事情,但它允许不同的代码样式。例如,您可以使用get fooset foo,写:

obj.foo++;

先调用getter,然后调用setter。例如,您当然可以让set 函数验证该值是否在特定范围内。传统代码如下所示:

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

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

这就是重点。我认为如果某样东西真的很昂贵,你就不应该使用 getter。

【讨论】:

    【解决方案2】:

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

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

    编写经典 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/setter 解决了这个问题。某些东西作为对象上的直接属性可读的事实不再告诉您有关该属性的实现的任何信息。它最初可能是一个字段,但最近变成了一个 ES6 属性访问器,而不需要更改 API。该属性的实现对代码库的其余部分隐藏,因此更容易更改。

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

    你是对的,这是一个风险。不过,这也是任何 getX() 的问题;有一个强烈的约定表明像 'getName()' 这样的简单方法不应该在幕后做昂贵的事情,即使它们是方法,如果你打破它,你几乎肯定会最终把人们赶出去(包括你自己,从现在起 6 个月)

    移动到属性不会改变这一点,但是你说得对,ES6 意味着你不再保证简单的属性访问是安全的。答案实际上只是你必须确保你(和其他所有人)坚持约定和Principle of Least Astonishment:与现有的简单外观的 getter 和 setter 一样,ES6 属性访问器应该做简单便宜的事情,并且不应该有奇怪的一面影响其他地方。

    【讨论】:

    • 请注意,JavaScript 从 ES5 开始就有 getter 和 setter,只有 class 语法是新的。
    • 周到。我想我从来没有遇到过所描述的场景的原因是除了公开的方法之外我从来没有公共属性。我依赖闭包封装。
    猜你喜欢
    • 2017-05-21
    • 1970-01-01
    • 1970-01-01
    • 2013-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-07
    相关资源
    最近更新 更多