利用jsdoc和idea加速javascript开发(一)

标签: 利用 jsdoc idea | 发表时间:2014-04-26 11:53 | 作者:zjumty
出处:http://www.iteye.com
当项目里的js代码到达一定规模后, js的开发会变成一个很头痛的问题, 由于没有静态类型语言的类型支持,很少有IDE能够对js代码提供有效的代码补全,方法和参数错误检查等功能. 想要在几万行js代码弄清楚某一个变量应该是什么类型, 有什么方法, 方法的参数是什么, 返回值是什么是件很令人头痛的事情.

幸好Intellij IDEA提供了对jsdoc的支持, 使我们可以更方便的编写js代码. 有时候我觉得IDEA对js的支持简直到了逆天的程度, 很少有IDE对js的支持能做到这么好.

我们先来看一个简单的例子, 下面的js程序
var doSomething = function(str, num){
    return {name : str, age : num};
};

doSomething(1, "terry");
doSomething("terry", 1);


上面的程序在运行期间是不会出错的.因为javascript是没有严格的类型检查.
但实际上,我们希望name属性是个字符串, 而age属性是一个数值类型. 这样我们的业务逻辑才有意义. 如果不是很清楚业务逻辑的开发人员调用doSomething方法时不小心用了doSomething(1, "terry"); 可能直到项目运行过程中发现页面上名字变成了数字, 或者年龄计算出错时才能发现这个问题.

同样是因为js的弱类型检查机制, 使得IDE也无法知道什么样的调用才算合理的. 所以即便是Intellij IDEA也会如下图的样子, 没有任何提醒.



事实上, 只有doSomething方法的作者本人才知道如何检查调用的方式正确的正确性. 幸运的是当我们在方法上加上正确的jsdoc以后, IDEA就会知道什么样的调用是合理的, 至少在参数的类型上是知道的. 所有加了jsdoc的IDEA会像下图的样子给出提醒



怎么样? 很不错是吧! 错误发现的越早, 修正错误的成本越低, 我想这是大家都认同的事实.

其实IDEA通过jsdoc对js程序的支持远不止这一个, 我们可以来看一下加上哪些jsdoc能让IDEA更好的为我们服务.

首先说一下jsdoc. 在javascript领域里没有想javadoc那样统一的标准, 也有好几种注释方式, 只能说jsdoc作为被使用较多和IDE支持较好, 成为了事实上标准. 但是每个IDE对jsdoc的支持程度也不仅相同.

关于jsdoc详细信息可以参见: http://usejsdoc.org/index.htm
在上面的网站上有详细的jsdoc的书写方法和生成jsdoc文档的工具的使用方法. 很多项目构建工具, 如maven, 也同样有生成jsdoc的支持.

Intellij IDEA对jsdoc的支持也不是100%的, 它目前支持的其实是Google Closure中的jsdoc变种, 但基本上和标准的jsdoc一致, 加入了一些类似泛型的支持(后面会讲到).相关信息参加这里: https://developers.google.com/closure/compiler/docs/js-for-compiler

下面我们会用"加入jsdoc之前"和"加入jsdoc之后"的区别来逐一看看IDEA对js到的支持. 由于这些特性在IDEA的文档里也没有明确指出, 基本上都是我试出来的, 所以可能会有遗漏的地方.

1. 函数的参数声明

上面的例子中已经看到了.
标签: @param {Type} varname Description
其实把varname放到{Type}前面IDEA也可以正确解析.

Type可以是JavaScript里面的原生类型,如String, Number. 也可以是自定义类型.

如果参数可以是可选的: @param {Type} [varname] Description

如果某个参数不是可选的, 但调用时没有指定值, IDEA提示错误, 如下:



num属性指定了可选以后则不会提示错误



在函数提示上也可以清楚的看到, num参数是可选的



通过@param {Number} [num=18]  a number parameter 可以指定默认值, 但是这只是在注释上使阅读更加清楚, 但IDEA并没有对这个支持

也可以用Google Closure的可选参数声明:
@param {Number=} num  a number parameter

2. 返回类型
在上面的例子中我们也通过@returns {{name: String, age: Number}}标签给返回值加了类型定义.

定义了返回值类型以后, 如果在函数体里实际返回的和声明的不一致, IDEA会给出提示:
需要的是一个有name和age属性的对象, 但是返回的是一个String



即便返回的是一个自定义对象, IDEA也会检查其中的属性是否满足要求:




在满足了要求的前提下, 增加别的属性是可以的:



缺少属性是不可以的:



如果某个属性是可选的, 可以用{Type=}的方式声明:



在声明了返回值以后, IDEA会自动把类型信息加入代码补全功能, 在上面的例子中,如果我们把函数调用的返回值赋给val4, 则val.的自动提示会是这样:



如果函数没有返回值, 不要加上@return标签

如果返回的结果值不可能为null, 则可以用@return {!String}, 如果在函数体里返回了null, IDEA会给出提示



如果函数返回值有可能是null, 最好在@return上声明出来@return {!String|null}
这样调用者会在自己的程序里加上null判断, 遗憾的是IDEA并没有对这个给予有效的提示, 如果能提供null校验提示就更好的. IDEA对Java是有类似的支持的.

3. 类型声明

回到上面的doSomething函数的例子:
/**
 * doSomething is a function
 * @param {String} str  a string parameter
 * @param {Number} num  a number parameter
 * @returns {{name: String, age: Number}}
 */
var doSomething = function(str, num){
    return {name : str, age : num + 1};
};

返回值的类型是一个复杂类型{{name: String, age: Number}}, 只有两个属性时还好, 代码不算多, 如果在多处使用copy一下成本不算太高. 如果属性比较多, 并且多处使用, 也就是说将来有可能到处修改那就麻烦了. 对于这种场景我们可以考虑使用两种方式: 定义真实的js类型, 定义虚拟的js类型.

定义真实js类型的方式有很多种, 这里是比较简单的一种:

/**
 *
 * @constructor
 */
var Employee = function(){
    /** @type String */
    this.name = "";
    /** @type Number */
    this.age = 1;
};

var emp = new Employee();
emp.name = "Terry";
emp.age = 18;


定义真实js类型的好处是, 运行期有类型信息, 可以通过构造函数进行复杂的参数控制. 但是当我们项目里有大量的充当VO功能的类型时定义真实类型就会很麻烦. 而且不灵活.

这时候定义虚拟类型会更加方便, 运行期不需要把这些定义告诉浏览器, 事实上浏览器也不关心. 虚拟类型是给IDE用的. 下面我们定义一个Manager类型:

/**
 * Manager virtual Type
 * @typedef {Object} Manager
 * @property {String} name
 * @property {Number} age
 * @property {Array.<Employee>} employees
 */

// var manager = new Manager(); 错误写法
/** @type Manager */
var manager = {
    name : "Terry",
    age : 28,
    employees : [
        {
            name : "Losyn",
            age : 18
        },
        {
            name : "Bruce",
            age : 18
        }
    ]
};


注意因为只是注释, 浏览器并不知道Manager这个东西, 所以如果执行var manager = new Manager();是会出错的.

我们可以把Manager声明为函数的参数,返回值, 或函数内部的变量的类型.

/**
 * Employee virtual Type
 * @typedef {Object} Employee
 * @property {String} name
 * @property {Number} age
 */

/**
 * Manager virtual Type
 * @typedef {Object} Manager
 * @property {String} name
 * @property {Number} age
 * @property {Array.<Employee>} employees
 */

/**
 * a function that a manager can make a order
 * @param {Manager} manager
 */
var makeOrder = function(manager){

};


IDEA会给出友好的代码补全功能:



声明变量类型

/** @type Manager */
var manger = $.parseJSON("{...}");


IDEA同样会给出友好的代码补全功能:



甚至数组中的元素的类型也能给出提示





除了上面的功能, IDEA对jsdoc还有很多丰富的支持, 由于篇幅太长, 我们在"利用jsdoc和idea加速javascript开发(二)"中讲解.

另外,很多时候我们都是把Java中的VO映射为Javascript中的类型, 如果项目上的VO较多, 变动频繁, 都要去手动维护就比较麻烦, 我写了一个自动把Java类型生成JavaScript类型定义的小程序: https://github.com/zjumty/java-to-jsdoc-object

已有 0 人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



相关 [利用 jsdoc idea] 推荐:

利用jsdoc和idea加速javascript开发(一)

- - JavaScript - Web前端 - ITeye博客
当项目里的js代码到达一定规模后, js的开发会变成一个很头痛的问题, 由于没有静态类型语言的类型支持,很少有IDE能够对js代码提供有效的代码补全,方法和参数错误检查等功能. 想要在几万行js代码弄清楚某一个变量应该是什么类型, 有什么方法, 方法的参数是什么, 返回值是什么是件很令人头痛的事情.

Guru Fuel:引爆idea

- Robert - I&#39;m TualatriX
咳咳…好久没更新日志了,这实际上是有原因的. 一方面是来帝都后还没完全进入状态,二是半个月前iPhone被偷,失去了一个重要的乐趣来源(悲剧…). 今天给大家介绍一个有意思的东西,它就是Guru Fuel. 今年四月份的时候,我曾经去上海的GuruDigger参加过一个有意思的活动——PythonVSRuby(详见《PythonVsRuby:让编程更有乐趣》).

为什么你不应该保密你的创业idea

- Taozi - 36氪
创业者创办公司时经常问的一个问题就是:我应该把我的idea多保密. 我的回答是:你应该跟每一个愿意听的人讲你的idea. 包括投资人,其他创业者,同行,朋友,大街上的人等. 向人们讲述你的idea有很多好处. 你将能够得到改进的建议,你会发现缺陷并有望改正,你将学到更多这个领域的知识,你将知道现在已经有哪些竞争产品,你可以通过产品的功能来估计人们对它的兴奋程度,你甚至可能发现你的idea是一个非常差的idea,然后你能够节省很多年的时间.

不必等到有了好 idea 才创业

- XiaoHui - 36氪
最近我遇见一个朋友,他说离开Google已经说了3年,每次我遇见他,他都说他只是“在等一个好的idea”就离开去创办自己的公司. 我猜他会跟很多人的做法一样,在Google呆另外的6-24个月,然后加入另外某个人的公司,他永远不会开始做任何事. 我认为“等有一个好的idea”才去创业的作法是绝对错误的,通常这种作法都会胎死腹中.

IntelliJ IDEA 开发商考虑推出 Google Reader 替代品

- - 博客园_新闻
在 Google 打算关闭其 Google Reader 服务后,大量类似的新闻聚合阅读解决方案浮现出来. 尽管这些阅读器各有各的特点,但对于用惯了 Google Reader 的用户来说,它们似乎缺少某些特性,使人不太满意,在功能上还不足以替代 Google Reader. IntelliJ IDEA 的开发商 JetBrains 放出话来,将考虑开发一款更加智能的新闻阅读器.

[转载]好的创业idea 都有哪些特点?

- - 蓝飞技术部落格
在《硅谷创业教父Paul Graham:如何获得创业idea》系列文章中,Paul Graham 在行文中暗含了好/糟糕idea 的特点/兆头,Nic Brisbourne 整理、归纳如下,仅供参考:. 这是创始人自己想要的产品/服务. 少有别人意识到这是值得做的事情. 这是一小群人迫切想要的,哪怕它只是一个粗糙的版本.

推荐系统领域有啥巧妙的idea? - 知乎

- -
机器学习中较为简单的算法有哪些. 》,很多同学私信我询问我FM算法在推荐系统中的应用细节,索性今天就专门写一篇文章,仔细聊一聊FM这把“. 机器学习算法中的瑞士军刀,可不是随便起的. 以前Xgboost因为方便易用、功能广泛、性能优异,被誉为Kaggle比赛中的瑞士军刀. 因为同样的优点,我将FM称作“推荐算法中的瑞士军刀”,其中有两个含意:.

用了这么久 IDEA,你竟然不知道 Live Templates ?

- - 掘金 后端
公众号「古时的风筝」,专注于后端技术,尤其是 Java 及周边生态. JavaNewBee 中,更有 Java 后端知识图谱,从小白到大牛要走的路都在里面. Live Templates 是什么,听上去感觉挺玄乎的. 有的同学用过之后觉得简直太好用了,不能说大大提高了开发效率吧,至少也是小小的提高一下,节省了很多敲重复代码的时间.

看了我常用的IDEA插件,同事也开始悄悄安装了...

- - 掘金后端本月最热
IDEA是程序员用的最多的开发工具,很多程序员想把它打造成一站式开发工具,于是安装了各种各样的插件. 通过插件在IDEA中完成各种操作,无需安装其他软件,确实很方便. 今天给大家分享下我平时常用的IDEA插件,个个是精品. SpringBoot实战电商项目mall(50k+star)地址: https://github.com/macrozheng/mall.