javascript - javascript 中的不可变类型

标签 javascript oop types immutability

在我看来,不可变类型在 Javascript 中是不可能的,或者有人知道创建它们的任何技巧吗?这是好事还是坏事?

例如,

var Point2D = function Point2D(x, y) {

    var _x = x;
    var _y = y;

    function constructor() {

        var self = {};

        // Pseudo-Immutable concept
        self.x = function() {
            return _x;
        }();

        self.y = function() {
            return _y;
        }();

        return self;
    }

    return constructor();

}

这当然不是真正不可变的,但如果它是 1) 充分证明属性 'x' 和 'y' 是 getter-functions 或 2) 在验证不可变性时抛出某种警报,那么它可以充当事实上的不可变对象(immutable对象)。

想法?

最佳答案

您可以使用 Object.freeze(o); 使对象在新的浏览器中不可变。

Point2D 可以这样实现:

var Point2D = function(x, y) { 
    this.x = x; 
    this.y = y;
    Object.freeze(this);
}  

现在不能向 Point2D 对象添加新属性,并且不能更改它的现有属性:

> var p = new Point2D(99, 123)
undefined
> p.x
99
> p.x = 7
7
> p.x
99
> p.foo = "This won't be added"
undefined
> JSON.stringify(p);
"{"x":99,"y":123}"

如果您只想锁定对象不添加任何新属性,那么您可以改用 Object.seal(o);。这将允许您更改现有属性,但不能添加新属性。

> var o = {x:1, y:2}
undefined
> Object.seal(o);
[object Object]
> JSON.stringify(o);
"{"x":1,"y":2}"
> o.foo = "This won't be added";
99
> o.x = 37 // Seal allows to mutate object 
37
JSON.stringify(o);
"{"x":37,"y":2}"

freezeseal 是 ECMAScript 5.1 的一部分 described more formally here

MDN说明 freeze 支持:

  • Firefox(壁虎)4 (2.0)
  • Chrome 6
  • Internet Explorer 9
  • 歌剧 12
  • Safari 5.1

或者,您可以使用更实用的编码风格:

var Point2D = function(x, y) { 
   return function(prop) { 
      switch (prop) {
         case "x": return x;
         case "y": return y;
         default: throw new Error("Property '" + prop + "' not supported");
      }
   };
}

用法如下:

> var p = Point2D(1,2)
undefined
> p("x")
1
> p("y")
2
> p("foo")
Error: Property 'foo' not supported

我知道无法使用此方法更改“属性”xy,因为它们受 Point2D 范围的约束> 功能。这种方法在 javascript 中并不常见(据我所知),但类似于在例如 Scheme 中实现消息传递/OO 的方式。

关于javascript - javascript 中的不可变类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7759672/

相关文章:

javascript - 如何将字符串解析为整数并保留小数位(如果它们为零)?

python - 类构造函数应该返回子类吗?

PHP 类的私有(private)属性和方法

scala - 是否可以将类型构造函数视为函数式编程语言中的类型?

Javascript ComboBox - 是否存在此特定功能的名称或示例?

javascript - Highchart - 将数据导出为 Excel 文件

javascript - 在文本框中按 Enter 键提交

javascript - 如何从另一个对象调用一个对象的方法?

asp.net - 无法隐式转换类型 'System.Data.Linq.ISingleResult<CustomeProcedureName> to ' int'

c - 为什么 C 中函数类型声明后面有一个星号?