在我看来,不可变类型在 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}"
freeze
和 seal
是 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
我知道无法使用此方法更改“属性”x
和 y
,因为它们受 Point2D
范围的约束> 功能。这种方法在 javascript 中并不常见(据我所知),但类似于在例如 Scheme 中实现消息传递/OO 的方式。
关于javascript - javascript 中的不可变类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7759672/