Sea*_*man 8 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();
}
Run Code Online (Sandbox Code Playgroud)
这当然不是真正不可改变的,但如果它是1)有充分证据表明属性'x'和'y'是getter-functions或2)在验证不变性时抛出某种警报然后它可以作为一个事实上不可变的对象.
思考?
Emi*_*l H 19
您可以使用Object.freeze(o);在新的浏览器中使对象不可变.
将Point2D因此可以实现这样的:
var Point2D = function(x, y) {
this.x = x;
this.y = y;
Object.freeze(this);
}
Run Code Online (Sandbox Code Playgroud)
现在,没有新属性可以添加到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}"
Run Code Online (Sandbox Code Playgroud)
如果您只想将对象锁定为没有添加任何新属性,则可以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}"
Run Code Online (Sandbox Code Playgroud)
freeze并且seal是ECMAScript 5.1的一部分,在这里更正式地描述
MDN表示freeze支持:
或者,您可以使用更实用的编码样式:
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");
}
};
}
Run Code Online (Sandbox Code Playgroud)
用法如下:
> var p = Point2D(1,2)
undefined
> p("x")
1
> p("y")
2
> p("foo")
Error: Property 'foo' not supported
Run Code Online (Sandbox Code Playgroud)
我知道无法改变"属性" x并y使用此方法,因为它们受Point2D函数范围的约束.这种方法在javascript中并不常见(据我所知),但类似于如何在例如Scheme中实现消息传递/ OO.
如果您不必担心较旧的浏览器,可以查看一下Object.defineProperty。
除此之外,我认为没有太多选择,因为可以在JavaScript中的任何位置重新定义对象的任何功能/属性。