js类型代替注释者优美也

类型注释

Javascript是动态类型语言,动态类型并不代表没有类型,它的类型是运行时决定的。阅读代码时,我们往往脑补变量的类型,是数字?还是字符串?很多时候读不懂代码,很大的原因是不能确定当前变量的类型,需要从变量定义处,函数调用处,去获知类型,一来二去阅读代码的思路就被打断了,不得不从头再来分析。这还算是运气好的,有些参数是多种类型,调用的地方又不在阅读的代码中,注释又是模糊不清,只能靠猜测,靠log,靠debugger,真是有苦说不出。

假如每读到一段代码就能明确的获知变量的类型,这不止会节省不少时间,还能开开心心的大呼:"阅读代码使我愉快"

这里我不是要介绍Typescript,Flow这些成熟的工具。我要介绍的是如何写类型才能传递给读者最明确,最关键,最舒心的信息。我会先介绍简单的类型然后接受==--(注:下面的类型全参考Haskell,也可以当做Haskell类型签名的介绍

简单类型

简单的类型不用写注释,一眼就能看出。

let name = "diqye" 
let index = 10
let isFoo = true

name 是 String , index 是 Number, isFoo 是Boolean

倘若只是声明不赋值或者赋值为null,需要标明类型(:这里是通过注释来标明

// String
let name
if (...) name = ...
else name = ....
// Number
let foo = null

函数的类型

函数分为两部分,一曰:输入,二曰:输出 即 参数列表和返回值。参数列表用括号括起来,假如只有一个参数可以不用括号,返回值放到->的后面。

// (Number,Number) -> Number
function add (a, b) {
  return a + b
}
// Number -> Number
let abs = n => Math.abs(n)

add函数接受两个Number参数,类型和实参一一对应, 返回值Number类型。

没有返回值

其实js中不存在没有返回值的函数,"没有返回值"的函数 返回的是 undefined,但是鉴于undefined太长,不美观,写起来不方便,而又很常见就用 () 代表undefined。

//  String -> ()
function mylogic (type) {
...somecode
}

上面这些很简单,注释也很自然,大家也很容易想得到。在简单的场景下即使不写类型注释,也很容易明确类型,下面开始介绍复杂的场景。

复杂的类型

有一些类型它不是单纯的一个值,需要和别的类型组合起来 如 Array,Promise,Object....。数组本身是一个类型,数组内包含的值又是一个类型。这样的类型称之为 带有参数的类型 (捂脸 不用纠结名字

// Array
let arr = []
...somecode
arr = [1,2]

如上面这样写,只能知道 arr是 Array ,并不知道arr里面是什么类型。改为如下就会好很多

// Array Number
let arr = []
...somecode
arr = [1,2]

现在可以通过注释中得知 arr是数组,数组里面是Number。鉴于Array是非常常见的类型可以用[Number]代表是数组类型,里面包含Number类型。

//[Number]
let arr = []
...somecode
arr = [1,2]

Object是通过多个别的类型组合而来。

// {name:String,age:Number}
let user = {name:'diqye',age:26}

Promise是js中内置封装异步操作的类型,在成功的时候通过then方法获取成功的data,在失败的时候通过catch方法获取错误的data。因此Promise内包含两个类型,一个是成功的时候的类型,一个失败的时候的类型 。 写作 Promise Type1 Type2。

// type Data = {name:String,age:Number}
// String -> Promsie Data String
function req(url){
 ...somecode
  return Promise
}

通过类型注释可以明确的知道数据是什么样的,请求成功我可以得到name,age 失败我得到的是一个字符串

类型变量

有的时候类型包含的类型是不明确的,往往需要在调用的时候明确,这时使用类型变量。前面介绍到的类型都是以大写开头的,如果以小写开头就视为类型变量,类型变量代表某一种类型。

//  a -> a
function id (b) { return b}
id(1) // 这时 上面的 a 代表Number
id('hello') // 这时 上面的 a 代表String

也就是类型变量在调用的时候确定变量所代表的类型。

下面通过高阶函数介绍,类型变量如何明确的表面一个函数的意图。

高阶函数

函数参数列表中有函数,或者返回一个函数,这样的函数称之为 高阶函数。以常见的forEach,map为例子

// ((a -> ()),[a]) -> ()
function forEach(fn,xs){
  xs.forEach.bind(xs)(fn)
}
// ((a -> b),[a]) -> [b]
function map(fn,xs){
  return xs.map.bind(xs)(fn)
}

forEach函数的类型注释表明了 forEach接受两个参数 无返回值(返回undefined) 。第一个参数是函数,这个函数入参是 a ,a 是后面数组中的a,无返回。第二个参数是数组。这样在使用forEach的时候就知道 我该传入怎样一个函数,并且根据函数名字也很容易想到是遍历数组调用函数。类型注释吧关键的信息都描述出来了。

map这个函数的类型注释更有意思了,接受 a -> b 的函数,一个[a]的数组 返回[b],再明白不过的标明了将[a] 通过 a -> b 的函数 变为 [b]了。

不知道你注意到了没有,我在描述map函数的时候 直接使用类型注释(如 a -> b)描述了,比用文字 (接受一个a返回b这样的一个函数)简洁多了,也易读多了。

Currying函数

关于什么是Currying函数 我这一篇文章有介绍

【js基础】js优美的实现自动Currying(柯理化),这里就不再多说了。

// Number -> Number -> Number
let add = curry(function(a,b){return a+ b})

没有新的规则,只需要把括号去掉就足以描述它了。有趣的是我们还可以进行推导。

// (a -> b) -> [a] -> [b]
let map = curry(function map(fn,xs){
 return xs.map.bind(xs)(fn)
})
// [Number] -> [Number]
let allAdd1 = map(add(1))

allAdd1这个函数是手工推导出来的。 数组中所有的值加1 ,还有比map(add(1)) + 类型注释 描述更简洁的方法吗?

最后

这里的类型注释参考的是Haskell,在Haskell里叫类型签名。虽只介绍了最基本的层面,但在js中能满足80%的场景,也没有深入的必要,毕竟JS中没有那么强大的类型系统。

初来简书,先试下水。 /捂脸

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,732评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,496评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,264评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,807评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,806评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,675评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,029评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,683评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,704评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,666评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,773评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,413评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,016评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,204评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,083评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,503评论 2 343

推荐阅读更多精彩内容