2010-12-15 27 views
17

来自C#/ PHP,我想在Javascript中创建的类(函数)上拥有完整的getter/setter。在Javascript中创建类getter/setters的最佳方法?

但是,在我遇到的大部分Javascript代码中,并没有使用getter和setter,而是使用了简单的公共变量。

我很高兴地发现在getter和setter John Resig's article,但它的一些意见,其中指出某些浏览器“不支持getter和setter”,这是混淆了我,因为他们不是一个“功能” Javascript支持,但是更多的一种使用基本Javascript语法的简单模式。这篇文章也是在2007年写的,所以现在可能已经过时了。

Javascript中getter和setter的当前状态是什么?今天他们是否确实被所有浏览器“支持”(无论这意味着什么)?他们是一个有用的编程模式的Javascript或Javascript类(功能)更好的公共变量?有没有比以下更好的方式来实现它们?

$(document).ready(function() { 
    var module = new Module('idcode'); 
    module.set_id_code('new idcode'); 
    module.set_title('new title'); 
    $('body').html(module.get_id_code()+': '+module.get_title()); 
}); 

function Module(id_code, title) { 
    var id_code = id_code; 
    var title = title; 

    //id_code 
    this.get_id_code = function() { 
     return id_code; 
    } 
    this.set_id_code = function(value) { 
     id_code = value; 
    } 

    //title 
    this.get_title = function() { 
     return title; 
    } 
    this.set_title = function(value) { 
     title = value; 
    } 
} 
+2

为什么你想要代码膨胀? – gdj 2010-12-15 14:30:49

+0

确切地说,我不想让代码膨胀,但我希望将公共和私人访问分离到我的类中,就像我在其他语言(如PHP和C#)中一样。 PHP有__get和__set魔术方法,而C#有它的“属性语法”来获得分离而没有臃肿的语法。在JavaScript中有这样的功能? – 2010-12-15 14:39:39

+0

以上代码段在IE 7/8/9中有效吗? – Shaggy 2014-09-26 07:20:05

回答

1

对于不支持属性语法的语言,getters和setters不是功能,而是“设计模式”(在这种情况下代码膨胀)。

由于Javascript不需要getter和setters,所以不需要编写它们。使用您可以使用的语言功能以及在一种语言中工作良好的习语在另一种语言中效果不佳。

我最喜欢的报价来自于Python的社区:

我们在这里的所有成年人自愿

讨论为什么不需要私有变量和信息隐藏时。

该报价可以发现here

了解语言为您提供什么,并接受其文化和规则。

+1

-1属性增变器对正确封装至关重要。允许对象进入另一个对象的内部会导致可怕的错误!它将无法保持内部状态的一致性。此外,该语言本身也支持getter和setter。 – 2015-05-04 22:27:51

5

如何:

function Module(id_code, title) { 
    var id_code = id_code; 
    var title = title; 

    var privateProps = {}; 

    this.setProperty = function(name, value) { 
     // here you could e.g. log something 
     privateProps[name] = value; 
    } 

    this.getProperty = function(name) { 
     return privateProps[name]; 
    } 
} 

这里的getter和setter方法行事用来存储不能从其他任何方法来访问性能的私人对象。因此,例如,无论何时修改属性(getter/setter方法的目的之一),您都可以实现一个记录或执行ajax或其他任务的setter(或getter)。

+2

这不提供任何有用的功能。 setProperty和getProperty是公共函数,所以这只是增加了一个间接级别。它不会添加调用私有getter和setter函数的功能。 – 2010-12-15 15:17:42

+0

它添加了除getter和setter方法外无法访问的属性 - 与使用公共getter和setter方法修改其他语言中的私有成员完全相同。这是一个示范 - 这些方法也可以做其他事情。 – sje397 2010-12-15 15:47:20

+0

够公平 - 但要么在代码中添加一个钩子来执行此操作,要么在代码中添加注释,以便修改行为。是的,这显然是资深的JavaScript程序员,但不是初学者。 – 2010-12-15 16:17:14

9

我想你错过了这一点。 (或者其他的应答者都缺少了这一点。)的ECMAScript提供了一个“背后的幕后”的getter/setter机制,使

x.foo = 3; 
y = x.foo; 

真正转化为(在某种程度上)

x.PutValue("foo",3); 
y = x.GetValue("foo"); 

其中PutValueGetValue是未命名的,对于属性的setter和getters不是直接可访问的函数。 (请参见ECMAScript standard, 3rd ed.,第8.7.1节和第8.7.2节)第3版似乎没有明确定义用户如何设置自定义getter和setter函数。 Mozilla对JavaScript的实现过程也有,例如(这是JSDB它使用JavaScript 1.8):

js>x = {counter: 0}; 
[object Object] 
js>x.__defineGetter__("foo", function() {return this.counter++; }); 
js>x.foo 
0 
js>x.foo 
1 
js>x.foo 
2 
js>x.foo 
3 
js>x.foo 
4 

的语法(或至少一直至今)浏览器专用。特别是缺乏Internet Explorer,至少根据this SO question

ECMAScript标准的第5版似乎在这个机制上标准化。见this SO question on getters and setters


编辑:一个更实际的例子,也许,你的目的:

function makePrivateObject() 
{ 
    var state = 0; 
    var out = {}; 
    out.__defineSetter__("foo", function(x) {}); 
    // prevent foo from being assigned directly 
    out.__defineGetter__("foo", function() { return state; }); 
    out.count = function() { return state++; } 
    return out; 
} 

js>x = makePrivateObject() 
[object Object] 
js>x.foo 
0 
js>x.foo = 33 
33 
js>x.foo 
0 
js>x.count() 
0 
js>x.count() 
1 
js>x.count() 
2 
js>x.foo 
3 
+2

这可能是他们如何在内部处理,但从技术上讲,如果我无法控制对他们的访问,他们仍然是“公共变量”。吸气剂和吸附剂的优点在于我可以确定例如“薪水”财产只能在内部更改,或(a)改变记录,(b)和事件被触发等等。除非我有getter/setter访问器方法,否则我没有能力为我的类定义这一层功能。 – 2010-12-15 15:19:35

+2

啊 - 但这里有一个微妙之处;如果你有能力使用自定义的getter/setter方法,你可以。我会编辑我的答案。 – 2010-12-15 15:32:50

14

火狐,Safari,Chrome和Opera(但不是IE)都具有相同的非标准gettersetter内置机制。ECMAScript 5包含一个不同的语法,即currently making its way into browsers,并将在未来成为标准。 IE 8已经具有此功能,但只能在DOM节点上使用,而不能使用常规的本机JavaScript对象。这是语法的样子:

var obj = {}; 

Object.defineProperty(obj, "value", { 
    get: function() { 
     return this.val; 
    }, 
    set: function(val) { 
     this.val = val; 
    } 
}); 
5

你实际上可以在JavaScript中定义setter和getters,而不仅仅是模仿它们。我认为它适用于除IE8及以下版本以外的所有浏览器。

$(document).ready(function() { 
    var module = new Module('idcode'); 
    module.id = 'new idcode'; 
    module.title = 'new title'; 
    $('body').html(module.id + ': ' + module.title); 
}); 

function Module(id, title) { 
    return { 
    id_code: id_code, 
    _title: title, 

    get id() { 
     return id_code; 
    }, 
    set id(value) { 
     id_code = value; 
    }, 

    get title() { 
     return _title; 
    }, 
    set title(value) { 
     title = value; 
    } 
    } 
}; 
2

我喜欢这样的:我赞成

// Module 
var Module = function() { 

    // prive getter/setter value 
    var __value; 

    // private getter/setter method 
    var _value = function() { 
     if(!arguments.length) return __value; 
     else __value = arguments[0]; 
    }; 

    // output/public  
    return { 
     value: _value 
    }; 
} 
0

一个可靠的,语义的方法是使用settersgetters。例如,我创建了以下对象:

var myComplexObject = { 
    changelog: {}, 
    log: function(name, val) { 
    console.log("set " + name + " to " + val); 
    if (!this.changelog[name]) 
     this.changelog[name] = []; 
    this.changelog[name].push(val); 
    }, 
    set o (val) { 
    this.log("o", val); 
    }, 
    get o() { 
    console.log("You will never know the true value!"); 
    return 42; 
    } 
} 

在这里,只要你读取或修改的o值,则该行为被定制。举个例子来说,下面的代码线及其控制台输出:

myComplexObject.o = "oxygen"; 
set o to oxygen 

然后,在该例子中,当试图在这对读出的值的结果:

var read = myComplexObject.o; 
console.log(read); 
You will never know the true value! 
42 

并且,在此示例中,您设置的每个新值都被记录:

myComplexObject.o = "Oh no!"; 
console.log(myComplexObject.changelog.o); 
set o to Oh no! 
["oxygen", "Oh no!"] 
相关问题