我正在编写一个我希望在高级模式下与Closure Compiler兼容的库。库中的大多数对象都维护着一个属性的内部对象,这些属性通常是API的一部分,这导致我的源文件中充满了很多很多这样的函数。
/*
* Get name.
*/
Layer.prototype.getName = function() {
return this.attrs.name;
}
/*
* Set name.
*/
Layer.prototype.setName = function(name) {
this.attrs.name = name;
}
我可以想出十亿种方法来优化它,以便稍微整理我的代码。一个例子:KineticJS,as per this related question,做了类似的事情:
Global.addGettersSetters = function(obj, property) {
obj['get'+property] = function() { return this.attrs[property] }
obj['set'+property] = function(val) { this.attrs[property] = val }
}
// Later that day, in our original object, we have:
Global.addGettersSetters(Layer, 'name');
我的理解是,使用Closure Compiler这是一个禁忌 - 名称不会被缩短,功能也不会被优化,因为我将Layer的属性指定为字符串
那么,有没有办法让我完全正确地定义界面而不会弄乱我的代码?封闭图书馆中有些东西我可能会忽略吗?
另一种解决方案:有没有办法在现代JS中做C#风格的属性?在某种程度上闭包编译器是允许的?我很擅长使用这个库定位Webkit和Webkit,所以还没有完全实现的东西很好。
答案 0 :(得分:3)
如果getters / setter无论如何都是公共的,那么你需要它们不能在缩小的js中重命名。这意味着让他们使用字符串来表示名字很好 - 他们不会缩小,但这就是你想要的。
答案 1 :(得分:1)
你不能动态添加一个函数,然后Closure Compiler可以对其进行编译(和缩小/混淆),因为动态的“addGettersSetters”函数只能在运行时使用,所以编译器不知道它可以创建什么。使用编译器的缺点是许多重复的预编译代码,但好处是使用getter和setter的大多数地方将被缩小或仅更改为对变量的内联引用。
此外,通过输入显式的getter / setter并使用JsDoc注释正确地注释它们:
/*
* Set name.
* @param {string} name
*/
Layer.prototype.setName = function(name) {
this.attrs.name = name;
}
您可以为代码添加一定级别的类型安全性,以确保在编译期间如果有人调用“setName(5)”时会收到警告。
否则我会遵循Chris的建议并研究JS getter / setters(其他参考here)。我没有在封闭编译器中使用它们,所以我不能保证它们。
答案 2 :(得分:0)
对不起,我没有得到ne8il答案以及为什么它被标记为正确答案。
您只需在.prototype
和obj
之间添加[
,即可按照以下要求执行操作:
function addGettersSetters(obj, property) {
// You can also add this if you don't want to declare attrs = {} each time
// if (!("attrs" in obj.prototype)) obj.prototype.attrs = {};
obj.prototype['get'+property] = function() { return this.attrs[property] }
obj.prototype['set'+property] = function(val) { this.attrs[property] = val }
}
并且还用大写字母书写属性名称。然后你可以像这样使用它:
var Layer = function() { this.attrs = {}; };
// Or just: 'var Layer = function(){};' if you use the line commented above
addGettersSetters(Layer, 'Name');
var layer = new Layer();
layer.setName("John");
alert(layer.getName()); // "John"
答案 3 :(得分:0)
不是原始问题的完整答案,只是添加一些信息。
您可以看到各种JavaScript OOP框架如何处理getter / setter,例如在这里:jsPerf.com - JavaScript Object Oriented Libraries Benchmark with getters and setters
Tan Nhu(基准测试的原作者)创建了他自己的OOP库jsface
,可在以下网址找到:https://github.com/tnhu/jsface
我喜欢它,我正是因为这个原因而使用它
编辑:如何在TypeScript中解决getter / setter生成器的解决方法,例如:在SO文章get and set in TypeScript
中有关其他框架及其编码getter / setter编码方式的更完整列表,您可以查看List of languages that compile to JS · jashkenas/coffeescript Wiki · GitHub