1 函数默认值
1 惰性解析:参数默认值不传值,每次执行函数的时候重新计算默认值表达式的值
let x = 99;
function foo(p = x + 1) {
console.log(p);
}
foo() // 100
x = 100;
foo() // 101
2 解构赋值和参数默认值,当设置了参数默认值时,若参数为undefined,则启用参数默认值;使用解构赋值时,函数执行时有实参则完全使用实参(包括实参为undefined时),若执行带参函数时不进行任何实参输入,则解构赋值生效
非尾部的参数值不可忽略,忽略会报错
3 length属性:函数预期传入的个数。
注意:设置默认值的参数不计入length,非尾部参数设置默认值后,后面的参数都不计入length
4 作用域
该部分复杂
参数设置默认值后,会生成单独作用域,该作用域与函数内部作用域不是同一个作用域,默认值若涉及变量,则从父作用域中查找,需要注意暂时性死区的情况
let x = 1;
function f(y = x) {
let x = 2;
console.log(y);
}
f() // 1
作用域不同的例子
var x = 1;
function foo(x, y = function() { x = 2; }) {
var x = 3;
y();
console.log(x);
}
foo() // 3
x // 1
var x = 1;
function foo(x, y = function() { x = 2; }) {
x = 3;
y();
console.log(x);
}
foo() // 2
x // 1
两者的差别在于是否用var声明x,若没有使用var,则直接使用默认值作用域的x,若声明了var,则x存在于函数作用域
2 rest参数
形式:(...变量名)
可获取函数的多余参数,生成一个数组,将多余参数放入数组
function add(...values) {
let sum = 0;
for (var val of values) {
sum += val;
}
return sum;
}
add(2, 5, 3) // 10
注意:只能作为最后一个参数
3 严格模式('use strict')
es6规定只要函数参数使用了默认值、解构赋值、或者扩展运算符,那么函数内部就不能显式设定为严格模式,否则会报错。
有两种方法可以规避以上限制:1.全局设定严格模式 2.把函数包在一个无参数的立即执行函数里面
const doSomething = (function () {
'use strict';
return function(value = 42) {
return value;
};
}());
4 一些新改变
1 name属性
给具名函数添加了name属性
function foo() {}
foo.name // "foo"
2 允许函数最后一个参数出现尾逗号
3 函数的toString
方法,将返回与函数一模一样的代码,es5去除了空格和注释
4 catch
命令可以省略参数
5 箭头函数(简化回调)
地狱难度
var f = () => 5;
// 等同于
var f = function () { return 5 };
var sum = (num1, num2) => num1 + num2;
// 等同于
var sum = function(num1, num2) {
return num1 + num2;
};
需要注意的点:
1 代码多余一条语句需要大括号({})包裹
2 若返回一个对象则该对象需要括号()包裹,因为JS引擎会把{}解释为代码块
3 没有自己的this
,内部this
指向父作用域的this
,其指向是固定的
4 不可对箭头函数使用new
5 箭头函数不可使用argument
对象
6 不可使用yield命令
6 尾调用优化
也不大好理解
简单来说就是在函数的最后一步调用另一个函数
function f(x){
return g(x);
}
其目的是只保留内层函数的调用帧,从而大大节省内存,但是递归调用容易造成栈溢出,所以建议用循环代替递归,而使用递归时尽量用尾递归