一、 函数 参数默认值
1. 规则
- (1)ES6 允许为函数的参数设置默认值: 在形参出直接定义即可,不用关键字声明
function ff(x, y = ‘World‘) {
console.log(x, y);
}
console.log(ff(‘Hello‘)); // Hello World
console.log(ff(‘Hello‘, ‘China‘)); // Hello China
console.log(ff(‘Hello‘, ‘‘)); // Hello
- (2)函数参数 在形参处默认声明: 规定 函数内不能用
let
或const
再次声明,否则会报错
function foo(x = 5) {
let x = 1; // error
const x = 2; // error
}
- (3)函数参数 设置默认值: 不会被记录到
函数.length
中函数.length
用于获取形参个数
(function (a) {}).length // 1
(function (a = 5) {}).length // 0
(function (a, b, c = 5) {}).length // 2
- (4)函数参数 设置默认值: 参数会在形参处 形成一个单独的作用域(conext)
var x = 1;
function f(x, y = x) {
console.log(y);
}
f(2) // 2
let x = 1;
function f(y = x) {
let x = 2;
console.log(y);
}
f() // 1
2. 函数参数 解构赋值
- 函数 参数为对象,设置默认值
function foo({
x = 10,
y = 5
}) {
console.log(x, y);
}
foo({}) // 10 5
foo({x: 1}) // 1 5
foo() // TypeError: Cannot read property ‘x‘ of undefined
function foo({
x = 10,
y = 5
} = {}) {
console.log(x, y);
}
foo({}) // 10 5
foo({x: 1}) // 1 5
foo() // 1 5
function foo({
x = 10,
y
}) {
console.log(x, y);
}
foo({}) // 10 undefined
foo({x: 1}) // 1 undefined
foo() // TypeError: Cannot read property ‘x‘ of undefined
- 重点区分
// 写法一
function m1({x = 0, y = 0} = {}) {
return [x, y];
}
// 写法二
function m2({x, y} = { x: 0, y: 0 }) {
return [x, y];
}
// 函数没有参数的情况
m1() // [0, 0]
m2() // [0, 0]
// x 和 y 都有值的情况
m1({x: 3, y: 8}) // [3, 8]
m2({x: 3, y: 8}) // [3, 8]
// x 有值,y 无值的情况
m1({x: 3}) // [3, 0]
m2({x: 3}) // [3, undefined]
// x 和 y 都无值的情况
m1({}) // [0, 0];
m2({}) // [undefined, undefined]
m1({z: 3}) // [0, 0]
m2({z: 3}) // [undefined, undefined]
// 写法三
function m3({x = 1, y = 0} = {}) {
return [x, y];
}
// 写法四
function m4({x = 1, y} = { x: 0, y: 0 }) {
return [x, y];
}
m1() // [1, 0]
m2() // [0, 0]
3. 函数参数默认值 的应用
- 应用一: 指定某一个参数,不能省略
function throwIfMissing() {
throw new Error(‘Missing parameter‘);
}
function foo(mustBeProvided = throwIfMissing()) {
return mustBeProvided;
}
foo()
// Error: Missing parameter
- 应用二: 某一个参数可省略
function foo(optional = undefined) { ··· }
二、 函数 的 rest 参数
ES6 定义了 rest 参数,用于获取函数的多余参数(在不确定函数有多少个参数时,最适用)
- 语法:
函数形参中
(...rest)
,在函数内部 变量rest
是存储着多余参数的一个真数组rest
只是一个变量,可以为任意值
function add(...values) {
let sum = 0;
for (var val of values) {
sum += val;
}
return sum;
}
add(2, 5, 3) // 10
add(2, 5, 3, 5) // 15
rest 参数 约束:
...rest
中包含的参数,不计入函数.length
中;当然,设置默认值的参数,也不计入函数.length
中函数的
...rest
参数必须作为函数的最后一个参数,其后 不能再有其他参数(否则 函数初始化时就会报错)
- 对比 ES5 中的
arguments
:arguments: 函数内部的一个属性,存储着函数中 所有实参的伪数组;
arguments
是固定值,函数内部直接访问即可; 箭头函数中不再支持 argumentsrest: 函数中的一个参数,存储着多余参数的一个真数组;
rest
是个变量,声明形参,才能在函数中访问
三、 箭头函数
1. 箭头函数 语法
箭头函数的 主要构成:
箭头函数 参数:不需要参数 或 需要多个参数,就使用 一个圆括号 代表参数部分
箭头函数 函数体:函数体重 多于一条语句,要使用 大括号 将它们括起来
箭头函数 返回值:函数体中 多于一条语句,且有返回值时 return 关键字不能省略
var sum = (num1, num2) => {
return num1 + num2;
}
最简化 的箭头函数
var f = v => v
- 省略了 参数圆括号、代码块中括号、return 关键字
var f = v => v;
// 等同于
var f = function(v) {
return v;
};
2. 箭头函数 this 指向
声明: 箭头函数 内部没有this属性;所以 箭头函数内 this 指向 外层代码块的 this
- 纠正:
ES5 语法中的函数,看this指向时的原则:谁调用了函数 this就指向谁
ES6 语法中的函数,分析this指向,只要找到箭头函数外层this指向即可(而不是看谁调用的函数)
<script>
const fn1 = {
name: function() {
console.log(this); // fn1
}
}
fn1.name();
const fn2 = {
name: () => {
console.log(this); // window
}
}
fn2.name();
</script>
<script>
let box1 = document.getElementById(‘box1‘);
box1.name = ‘wang‘
this.name = ‘zhang‘;
box1.addEventListener(‘click‘, function() {
console.log(this.name); // ‘wang‘ 因为是dom对象,调用了回调函数
});
let box2 = document.getElementById(‘box2‘);
box2.name = ‘wang‘
this.name = ‘zhang‘;
box2.addEventListener(‘click‘, () => {
console.log(this.name); // ‘zhang‘ this.指向外层的this
});
</script>
- 借用方法
call
、apply
、bind
,不能改变 this指向
var a = 2;
var obj = {
a: 100
};
var fn1 = (a) => {
console.log(this.a);
};
var fn2 = function(a) {
console.log(this.a);
};
fn1.call(obj); // 2
fn2.call(obj); // 100
3. 箭头函数 的约束
箭头函数 不能当作 构造函数(因为 自身没有 this 机制)
箭头函数内 不能使用arguments对象, 用 rest 参数代替
箭头函数 中没有
arguments
、super
、new.target
这是三个变量, 均指向外层函数 的变量
四、 函数的 name 属性 被写入标准
函数的
name
属性, 早就被浏览器广泛支持,但是直到 ES6,才将其写入了标准- 对比:
写入标准之前:将 匿名函数 赋值给一个变量;访问
函数.name
返回空字符串写入标准之后:将 匿名函数 赋值给一个变量;访问
函数.name
返回 变量名
const test = function baz() {};
console.log(test.name); // ES5输出:""
console.log(test.name); // ES6输出:"baz"
五、 函数内 关于 严格模式的约束
ES2016 规定: 函数参数 如果使用了默认值、解构赋值、扩展运算符,函数内部就不能显式设定为严格模式(否则会报错)
原因猜想: (待证实)可理解为函数式一个整体,函数 执行的时候:先执行函数参数,然后再执行函数体;函数执行到中间 发现语法 要遵循 严格模式,就会报错
解决方案:
// 方案一:
‘use strict‘;
function doSomething(a, b = a) {
// code
}
// 方案二:
const doSomething = (function () {
‘use strict‘;
return function(value = 42) {
return value;
};
}());