所有函数都是Function的实例(包括Function本身)
arguments
虽然 arguments 很像数组,但它是一个对象。数组专有的方法(比如 slice 和 forEach ),不能在arguments 对象上直接使用。
如果要让 arguments 对象使用数组方法,真正的解决方法是将 arguments 转为真正的数组。下面是两种常用的转换方法:slice 方法和逐一填入新数组。
// 使用call()盗用slice()方法
function foo(a,b,c){
var args = Array.prototype.slice.call(arguments);
console.log(args.slice(0, 2));
}
foo(4, 5, 6); // [4,5]
// 遍历逐一填入数组
var args = [];
for (var i = 0; i < arguments.length; i++) {
args.push(arguments[i]);
}
模拟函数重载
用 arguments 对象判断传递给函数的参数个数,即可模拟函数重载。
function doAdd() {
if(arguments.length == 1) {
alert(arguments[0] + 5);
} else if(arguments.length == 2) {
alert(arguments[0] + arguments[1]);
}
}
doAdd(10); // 15
doAdd(40, 20); // 60
默认参数
// es5
function show (msg,duration) {
duration = duration || 3000
...
}
// es6
function show (msg,duration = 3000) {
...
}
函数调用中跳过参数
// es6 传递一个 undefined 会使用默认值
function sayHi(arg1=1,arg2=2,arg3=3){
console.log(arg1, arg2, arg3)
}
sayHi('第一个参数',undefined,'第二个参数')
// 传递一个对象
function sayHi(person){
let name = person.name
let height = person.height
console.log(name, height)
}
sayHi({name:'lxx',age:25,height:1.88})
函数名解耦
arguments.callee 指向拥有这个 arguments 对象的函数。
function box(num) {
if (num <= 1) {
return 1;
} else {
return num * arguments.callee(num - 1);
}
}
box(5)
柯里化
只传递给函数一部分参数来调用它,让它返回一个函数处理剩余的参数。
// 未柯里化
function add1(x,y,z) {
return x + y + z
}
add1(10,20,30)
// 柯里化处理的函数
function add2(x) {
return function(y) {
return function(z) {
return x + y + z
}
}
}
add2(10)(20)(30)
单一职责原则
每一个函数处理的问题尽可能单一,避免将众多处理过程交给一个函数。
// 未柯里化
function sum(x,y,z) {
x = x + 2
y = y * 2
z = z * z
return x + y + z
}
sum(10,20,30)
// 柯里化
function sum(x,y,z) {
x = x + 2
return function (y) {
y = y * 2
return function (z) {
z = z * z
return x + y + z
}
}
}
sum(10)(20)(30)
柯里化逻辑复用案例1
function makeAdder(count) {
// ... 如果还有其他逻辑
return function (num) {
return count + num
}
}
// 用法一
makeAdder(10)(10) // 20
makeAdder(20)(10) // 30
// 用法二
var adder5 = makeAdder(5) // 这里就是对 makeAdder 其他逻辑的复用
adder5(10) // 15
adder5(20) // 25
adder5(30) // 35
柯里化逻辑复用案例2
传统方式:每一个参数都需要传递,存在重复传递。
function log(date,type,message) {
console.log(`[${date.getHours()}:${date.getMinutes()}]-[${type}]-[${message}]`)
}
log(new Date(),'debug','轮播图错误')
log(new Date(),'debug','菜单错误')
log(new Date(),'debug','编辑器错误')
柯里化方式
function log(date,type,message) {
return function (type) {
return function (message) {
console.log(`[${date.getHours()}:${date.getMinutes()}]-[${type}]-[${message}]`)
}
}
}
// 将 date 提取出,不需要传递,只传递 type 和 message
var nowLog = log(new Date())
nowLog('debug')('标题栏错误')
nowLog('debug')('编辑器错误')
// 将 date 和 type 提取出,不需要传递,只传递 message
var nowMessage = log(new Date())('debug')
nowMessage('登录错误')
nowMessage('注册错误')
箭头函数柯里化
var log = date => type => message => {
console.log(`[${date.getHours()}:${date.getMinutes()}]-[${type}]-[${message}]`)
}