标签:|| 等价 函数表达式 func erro param return 注意 运算
第三章 函数
函数形参的默认值
ES5模拟默认参数
function makeRequest (url, timeout, callback) {
timeout = timeout || 2000;
callback = callback || function () {};
}
为形参赋予默认值,说明了该参数为可选参数。
ES6的默认参数值
function makeRequest (url, timeout = 2000, callback = function () {}){
// 函数执行
}
需要注意的是,在参数中,null也是合法的参数值,所以传入null的时候不会用默认值替代。
ES6真正的可选参数是参数后面带?声明。
默认参数值对arguments对象的影响
在ES5非严格模式中,函数命名参数的变化会体现在arguments对象中。
在ES5严格模式中,无论参数如何变化,arguments对象不再随之改变。
ES6默认处于严格模式,默认参数值的存在使得arguments对象保持与命名参数的分离。
默认参数表达式
默认参数值可以使用任意数据类型,甚至是函数执行返回的结果。
ES6的参数声明具有临时性死区的特性,不能在声明之前调用。
function add (first = second, second = 1) {
return first + second;
}
// 这是一个运行时才会抛出的错误,只有当first传入了非法值,引发默认值赋值的时候,才会抛出error。
add(1, 2); //3,没有使用默认值
add(); // ReferenceError,使用默认值时候发现在second声明前使用了second
处理无命名参数
ES5中的无命名参数
ES5调用arguments对象来获取所有的实参,从而间接地对无命名参数操作。
不定参数
ES6引入在命名参数前的三个点...来表明不定参数(rest parameters)。所有自它之后传入的所有参数,都被纳入以这个参数命名的数组中。ES6中arguments依然存在,但是应当尽可能地使用不定参数来替代它的作用。
使用限制:
增强的Function构造函数
ES6增强了Function构造函数的功能,支持在创建函数时定义默认参数和不定参数。
var add = new Function('first', 'second = 1', 'return first + second;');
add(1, 1); // 2
add(1); // 2
name属性
ES6为所有函数添加了name属性,其特性为:
不能使用name来获取对于函数的引用。
展开运算符
和不定参数使用相对的是展开运算符,同样也是...声明。
它使用在传递实参的时候,将一个Array展开为参数表的形式。
let values = [25, 50, 75, 100];
// 两者等价
Math.max.apply(Math, values);
Math.max(...values);
明确函数的多重用途
JS函数有两个不同的内部方法: [[Call]]和[[Construct]]。
通过new关键字调用函数时,执行的是[[Construct]]函数,它负责创建一个实例对象,然后再执行函数体,将this绑定到实例上。
不通过new调用函数,则执行[[Call]]函数,直接执行代码中的函数体。
ES5判断函数被调用方法
使用this instanceof class的形式。
function Person (name) {
// new关键字将this绑定到实例
if(this instanceof Person) {
this.name = name;
}
// [[Call]]调用不会绑定this到实例
else {
throw new Error('必须使用new关键字调用Person');
}
}
元属性(Metaproperty)new.target
new.target表示new操作符的目标,即该构造函数。如果[[Call]]方式调用,则其为undefined。
块级函数
ES6引入块级作用域后,在块级作用域中声明的函数只能在块内使用,当跳出块后,该函数将无法访问。
严格模式下,function声明的块级函数会被提升到块级作用域的顶部。
非严格模式下,function声明的跨级函数会被提升到外层的函数作用域。
箭头函数(Lambda)
与传统函数的不同:
lambda表达式也有name属性,类似于函数。
没有this绑定
lambda表达式的this必须通过查找作用域链来决定其值。
箭头函数的返回值
没有用{}包裹时,lambda表达式只能有一条执行语句,并返回该语句的返回值。
var result = [].sort((a, b) => a - b); // 等同于 return a - b
尾递归优化(TCO)
function TCO (fn) {
let value,
active = false,
accumulated = [];
// 在f内部进行递归调用的时候,其实调用的是这个返回的accumulator
// 这里需要注意的是,要将f中的递归调用函数名使用accumulator被赋予的变量名
return function accumulator(...args){
accumulated.push(args);
if(!active) {
active = true;
while(accumulated.length) {
/**
* 由于每次需要递归的fn.apply都会导致accumulated被push进一个新的arguments,
* 所以这个while一直要到全部执行结束才会跳出,
* 但这种结构只会保持最多两层的调用栈
*/
value = fn.apply(this, accumulated.shift());
}
active = false;
return value;
}
}
}
var sum = TCO(function(x, y) {
if(y > 0) {
// 再次调用的其实是闭包返回的accumulator,而不是这个传入的function
return sum(x + 1, y - 1);
} else {
return x;
}
});
标签:|| 等价 函数表达式 func erro param return 注意 运算
原文地址:https://www.cnblogs.com/gaogao999/p/11097579.html