我使用闭包编译器编译我的源代码,当我调用一个从网络获取事件对象的函数时,应用程序在控制台中抛出错误。
调用的函数是:
/**
* @param {goog.events.Event} event Socket.io-Wrapper Event.
*/
de.my.app.admin.prototype.onSaved = function(event){
var category = event.data[0].category; //<-- here it throws the error because category get compiled.
var id = event.data[0].id;
var oldid = event.data[0].oldid;
[...]
}
事件对象看起来像这样
{ data:{
0: {
category: 'someString',
id: 5,
oldid: -5
} }
[...someMoreValuesAddedBySocketIO...]
}
这是我预期的行为。
现在我将这样的外部声明添加到我的外部文件,但我没有改变函数中@param
的类型声明,错误消失了:
var xterns;
/**
* @typedef {{
* category : string,
* oldid : number,
* id : number
* }}
*/
xterns.NOTUSEDNAME;
/**
* @type {string}
*/
xterns.NOTUSEDNAME.prototype.category;
/**
* @type {number}
*/
xterns.NOTUSEDNAME.prototype.oldid;
/**
* @type {number}
*/
xterns.NOTUSEDNAME.prototype.id;
简而言之:我有一个@param {goog.events.Event} event
声明,xterns.NOTUSEDNAME
的extern解决了编译器问题......
任何人都可以解释为什么会这样吗?
答案 0 :(得分:3)
这是一种常见的误解。如果任何 extern对象包含同名属性,Closure-compiler将不会重命名属性。请参阅FAQ。如果启用了基于类型的优化,那么这不再是真的,我希望你的代码再次中断。
要使此代码类型安全并在没有警告的情况下进行编译,您需要:
使用引用的语法event.data[0]['category']
引用数据属性。编译器永远不会使用此方法重命名您的属性(通常由JSON数据使用)。
使用自定义对象扩展goog.events.Event
类型,该对象将数据对象定义为强类型数组。
示例:
/**
* @constructor
* @extends {goog.events.Event}
*/
de.my.app.AdminEvent = function() {};
goog.inherits(de.my.app.AdminEvent, goog.events.Event);
/** @type {Array.<{category:string, id:number, oldid:number}>} */
de.my.app.AdminEvent.prototype.data = [];
根据您的具体情况,界面可能是更好的选择。