闭包编译器外部解决了一个问题,但我不明白为什么

closure compiler externs solves an issue but i didn't understand why?

本文关键字:问题 为什么 明白 一个 解决 外部 编译器 闭包      更新时间:2023-09-26

我用闭包编译器编译源代码,当我调用从网络获得事件对象的函数时,应用程序在控制台上抛出错误。

调用的函数是:

/**
 * @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...]
}

这是我所期望的行为

现在我添加了一个像这样的externs声明到我的externs文件,但我没有改变@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对象包含相同名称的属性,闭包编译器将不会重命名属性。请参阅FAQ。如果启用了基于类型的优化,那么这将不再是真的,并且我预计您的代码将再次中断。

要使此代码类型安全且编译时没有警告,您需要:

  1. 使用引号语法event.data[0]['category']引用数据属性。你的属性将永远不会被编译器使用这个方法(JSON Data经常使用)重命名。

  2. 使用自定义对象扩展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 = []; 

根据具体情况,界面可能是更好的选择。