Javascript 什么是谷歌关闭';你到底是怎么做的?

Javascript 什么是谷歌关闭';你到底是怎么做的?,javascript,google-closure,jsdoc,Javascript,Google Closure,Jsdoc,我了解它的用途——我可以看到为复杂类型定义别名并在文档中使用它的好处。所以你可以定义一个类型,比如 /** @typedef {{x:number, y:number}} */ example.Point; /** * @param {example.Point} point * @return {example.Point} */ example.functionThatTakesAPointAndReturnsAPoint(point) { .... } …然后用它来记录一个函数,

我了解它的用途——我可以看到为复杂类型定义别名并在文档中使用它的好处。所以你可以定义一个类型,比如

/** @typedef {{x:number, y:number}} */
example.Point;
/**
 * @param {example.Point} point
 * @return {example.Point}
 */
example.functionThatTakesAPointAndReturnsAPoint(point) {
....
}
…然后用它来记录一个函数,比如

/** @typedef {{x:number, y:number}} */
example.Point;
/**
 * @param {example.Point} point
 * @return {example.Point}
 */
example.functionThatTakesAPointAndReturnsAPoint(point) {
....
}

但我不确定的是,如果它只用于文档和编译器的静态类型检查,那么为什么typedef需要这行JavaScript?别名不能完全在文档注释块中定义吗?而且,如果您直接提供代码(不编译代码),JavaScript解释器会如何处理typedef注释后的那行代码?

这不仅仅是为了文档。当您使用闭包编译器编译脚本时,它还会向您发出警告

闭包编译器可以使用有关JavaScript的数据类型信息 变量以提供增强的优化和警告。JavaScript, 但是,无法声明类型


实际上,您可以直接在方法文档中设置类型声明:

/**
 * @param {{x:number, y:number}} pointLike
 */
var myFn = function(pointLike) {
 return pointLike.x + ':' + pointLike.y;
}

alert(myFn({x:34, y:20}))
alert(myFn({x:34, y:'20'})) // will trigger compile time type warning
对于在多个地方使用的对象类型,使用
@typedef
的好处在于可用性/清晰度更高

例如:也许不久你会得到一个“Point.z”attr。使用typedef,您只需更新typedef声明,而不必更新整个代码库中的每个内联类型声明


另请参见

编译器构建在Rhino之上,只是增强了可用的语法。我认为从no-op属性访问中获取别名更容易,因为它与标准模式匹配。

如果在注释中定义整个typedef会更好。将它的一部分定义为代码会产生一些意想不到的后果。看这个


在实际代码中定义typedef名称的原因是解析和类型检查在闭包编译器中的工作方式。解析器需要将每个jsdoc注释附加到AST节点,否则注释将被静默忽略。因此,typedef的名称被定义为代码,jsdoc被附加到它上,之后typechecker将获取类型定义。

谢谢-我明白了这一点……我只是有点困惑,为什么它需要那行JavaScript代码来实现这一点。例如,为什么typedef不能像/**@typedef{{{{x:number,y:number}}example.Point*/。我对JavaScript还比较陌生,所以我只是想确保那里没有我不理解的东西。谢谢-我想这就是我想要的信息。因此,typedef后面的那行JavaScript什么也不做……基本上是为了方便而这样实现的。