原型的getter和setter是什么类型的对象/属性?

4

阅读John Resig关于Javascript getters和setters的文章,我发现了一个在Javascript中我不熟悉的结构:

Field.prototype = {
    get value(){
        return this._value;
    },
    set value(val){
        this._value = val;
    }
};

原型是一个像许多其他对象一样的对象,但这里的获取和设置部分似乎不太熟悉。它们看起来不像对象的 typica 属性(遵循 "key":"value" 语法),也不完全像标准函数。
这只是JS引擎将其转换为更易于识别的东西的简写吗?
更新:
我的问题的实质是:既然 { foo(){} } 不是有效的语法,那么在给定 get 或 set 操作符的情况下,是什么使其有效? { get foo(){} }

1
getset都在MDN的运算符文档中列出。https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/get。它们也被称为getter和setter。我猜它们类似于`delete`/`typeof`/`yield`运算符。 - CodingIntrigue
啊,当我了解到它的时候,我感觉有点肮脏。在我看来,这些东西永远不应该存在。 - ZenMaster
谢谢@RGraham。我刚在MDN上找到了一些关于get操作符的信息。接下来真正重要的是它如何与对象字面量表示法相结合。它们被视为特殊情况还是这种语法实际上是标准的? - Jamie Dixon
1个回答

4
我花了一点时间阅读才明白它的用法,所以虽然 @RGraham 指向了一段好的文档 (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/get),但我想提供一个使用示例。
基本上, "get" 和 "set" 运算符允许您覆盖直接访问成员变量时获取的行为。
这意味着您可以,例如:
- 以一个名称公开地呈现一个成员变量,然后将其私下存储为另一个名称。 - 存储之前对值执行操作。 - 呈现一个看起来像成员变量而实际上是函数的东西。
当然,所有这些都可以通过在对象上定义函数来完成,区别在于函数必须被称为这样。
使用这种记号时,即使记号似乎引用成员变量,也会调用函数。
就个人而言,我不喜欢它 - 我认为它可能会导致一些非常令人困惑的代码,特别是在调试时。但如果您想要使用它,那么它就在那里...
示例
var Field = {
    get value(){
        return this._value;
    },
    set value(val){
        this._value = val + 1;
    }
};

Field.value = 100

console.log( Field.value );

将输出:

101

这里有一个示例: http://jsfiddle.net/zV8Kf/1/

接下来是关于“为什么{ get foo(){} }是合法的?”问题:

我的理解是:

  • 创建一个对象
  • 定义一个无操作的函数
  • 把该函数分配给'foo'作为getter

这意味着对于该对象的foo引用将返回undefined

您可以在此处查看行为:

http://jsfiddle.net/VHAhA/

如果您认为get近似于foo: function(我知道它不完全如此,但它确实说明了“我要定义一个函数-将其分配给this”),那么它在语法上类似于:

{ foo: function foo() {} }

它不能与{ foo(){} }进行比较,因为在这个例子中,您没有告诉JavaScript您将要定义什么,也没有告诉它在定义之后把它放到哪里。


嗨,罗布。感谢你抽出时间回答我的问题。我对语法的目的和用法其实还好。我知道它是如何工作的以及可以用于什么,所以我的问题仍然是关于这种语法与其他对象的差异。由于{ foo(){} }无效,为什么使用get运算符就有效呢? - Jamie Dixon
我不确定你的意思。你能否在原问题中提供更充分的例子,例如“这是无效的”、“这是有效的”、“为什么?”。 - Rob Baillie
感谢你加上最后一部分,Rob。这是JS引擎实际执行的操作吗?它会将其扩展为你提供的完整形式,还是其他事情正在发生? - Jamie Dixon
不好意思,我不知道!那已经超出了我的知识范围。话虽如此 - 我非常怀疑,因为它的行为明显不同。getter和setter定义覆盖foo.bar的行为,而不仅仅是定义了foo.bar()的行为。如果您在第一个示例中使用console.log输出对象,则会看到get valueset value被定义为对象中的不同实体。 - Rob Baillie
感谢您花时间回答我的问题,Rob。我觉得我离理解更近了一步。 - Jamie Dixon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接