在Javascript中生成与Closure Compiler兼容的getter和setter

时间:2013-04-23 00:29:03

标签: javascript google-closure

我正在编写一个我希望在高级模式下与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,所以还没有完全实现的东西很好。

4 个答案:

答案 0 :(得分:3)

如果getters / setter无论如何都是公共的,那么你需要它们不能在缩小的js中重命名。这意味着让他们使用字符串来表示名字很好 - 他们不会缩小,但这就是你想要的。

是的,modern JS has getters/setters

答案 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答案以及为什么它被标记为正确答案。

您只需在.prototypeobj之间添加[,即可按照以下要求执行操作:

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