可以在函数上挂载一些标记属性,如该函数是否可用、函数序号、使用环境等等与该函数有关的特征信息。
// 例1:函数的封装者标记 function fn(){} fn.useAble = false // 例2:函数集合去重存储 var fnStore = { nextId: 1, cache: {}, add: function(fn) { if (!fn.id) { fn.id = this.nextId++; this.cache[fn.id] = fn; return true; } } }; function fn1(){} fnStore.add(fn1) 1234567891011121314151617在某函数运行的时间复杂度高或返回值比较密集时,可以用空间换时间,通过在该函数上挂载一个结果集对象的属性的方式,在具体运算前先对该对象进行搜索,有则取值返回,无则运算后得值存储下来并返回,这样可以大大加快运行速度,如下例:
// 例1: function fn(param){ if(fn.results){ fn.results = {} } if(fn.results[param] !== undefined){ return fn.results[param] } else{ const result = ...xxx // 函数具体逻辑 fn.results[param] = result } } 12345678910111213在我们经常见到的api当中,很多除核心逻辑外的封装以及语法糖,尤其是对该函数的一些常用的构造方式,都会被封装成一个工具函数,然后作为属性挂载在该封装函数上,如下例:
// 例1:Promise的工具函数resolve、reject、all、race等函数都通过函数属性方式挂载在Promise上,而不是作为实例方法或原型方法挂载在每个实例对象或者原型对象上。 function Promise(excutor){} Promise.resolve = function(value){} // 注意这里不是回调函数参数resolve,而是Promise工具函数resolve,用来快速得到一个resolved状态的Promise。 Promise.reject = function(error){} // 与上同理 Promise.all/race/xxx = function(){} // 例2:axios function axios(){} axios.get = function(url){} // 以及axios.post/delete/put等工具函数都是挂载在axios上 12345678熟悉Java的人都知道,在Java中,方法并不是一个独立的对象,也没有方法单独的存储方式,所以它不可能作为引用类型或者基本类型传递。但是在JavaScript中函数或者方法传递是可以做到的,因为函数是对象,所以它可以被存储并被传递。
function fn(){ console.log(111) }; setInterval(fn1, 1000) 12有关生成器函数更详细的内容,会在另外一篇博客再做研究,在这里不展开讨论。
为函数的最后一个命名参数前加上省略号(…)前缀,这个参数就变成了一个叫作剩余参数的数组,数组内包含着传入的剩余的参数,如下例:
// 使用ab当中更大的一个值加上除a、b匹配的实参外的后续所有实参的值 function fn(a,b,...rest) { const sum = a>b?a:b for(i of rest){ sum += i } return sum } fn(1, 2, 3, 4) // 结果为9 123456789隐式参数在函数声明中没有明确定义,在函数调用时也没有显示传入,但会默认传递给函数并且可以在函数内正常访问,同时在函数内可以像其他明确定义的参数一样引用它们,详细内容后面会再讨论。