【JavaScript进阶之旅 ES6篇 第六章】函数默认值、this、箭头函数、箭头函数结合函数参数解构赋值、rest运算符

本文深入探讨JavaScript中函数参数的默认值、实参length属性、形参实参映射、解构赋值默认值、fetch用法、作用域规则、函数this指向以及箭头函数的特性。特别强调了函数默认值如何影响length属性,this在不同场景下的绑定规则,以及箭头函数与普通函数的区别,如arguments对象的缺失和rest运算符的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、函数默认值

1、函数形参的length

function test(a, b, c) {}
console.log(test.length); // 3

function test(a, b = 1, c) {}
console.log(test.length); // 1
  • 函数形参的length等于从左到第一个有默认值的参数的个数

2、函数实参的length

function test(a, b, c) {
  console.log(arguments.length); // 2
}
test(1, 2);

  • arguments.length

3、函数的默认值对函数的length的影响

  • 更改函数参数默认值,会引起函数的属性length变化
  • length根据默认值的位置确定,只包含默认值之前的参数的长度

4、函数的默认值导致形参和实参的映射关系不存在

  • 函数的形参和实参是相互映射的关系
function test(a, b, c) {
  arguments[1] = 3;
  console.log(b); // 3
}
test(1, 2);

指定函数的默认值后:

function test(a, b = 5, c) {
  arguments[1] = 3;
  console.log(arguments); // [1, 3]
  
  console.log(b); // 2
}
test(1, 2);
  • 任何一个参数给了默认值后,形参跟实参的映射关系将不存在
  • 函数内部更改实参的值,能够更改实参,但是对形参没有任何影响

5、给解构赋值一个默认值

function foo({x, y = 5}) {
  console.log(x, y);
}

foo({}); // undefined 5
foo({x: 1}); // 1 5
foo({x: 1, y: 2}); // 1 2

foo(); // 报错 因为他没有属性则没有包装类,匹配不上{},所以报错

上述不传值的解决办法:

function foo({x, y = 5} = {}) { // 解构赋值依然有默认值 {}
  console.log(x, y);
}

// 参数是undefined的时候会找默认值为空对象的默认值,从而达到匹配
foo(); // undefined 5

6、fetch

// 简写方式
function fetch(
  url,
  {
    body = "",
    method = "GET",
    header = {}
  }
) {
  console.log(method);
}

// 完整方式
function fetch(
  url,
  {
    body: body = "",
    method: method = "GET",
    header: header = {}
  }
) {
  console.log(method); // GET
}

fetch('http://www.baidu.com', {});

调用fetch的时候,不想手动传第二个参数,那么我们就可以给他的解构赋值赋一个默认值:

function fetch(
  url,
  {
    body = "",
    method = "GET",
    header = {}
  } = {}
) {
  console.log(method);
}

fetch('http://www.baidu.com'); // GET

7、作用域问题

var a = 1;
var a = 2; // var存在变量提升,可以重新赋值,覆盖
console.log(a); // 2

var x = x; // x声明到全局,没有赋值
console.log(x); // undefined 

let b = 1;
let b = 2; // let不存在变量提升,不可以重新赋值,报错

let c = c; // c没有声明 报错 c is not defined
// x还没有定义,不可以在初始化之前调用x 
function foo(x = x) { // Cannot access 'x' before initialization
}

foo();

8、默认值给一个function

  • 调用栈:函数调用的时候会创建一个栈针,记录着当前的函数是在哪个地方调用的,以栈的方式存储
var x = 1;
// 当给函数默认值的时候,就已经给了一个块级作用域 let x,y
function foo(x, y = function() {
  x = 2;
  console.log(x); // 2
}, z = function() {
  console.log(x);
}) {
  var x = 3;
  y(); // 2
  console.log(x); // 3
  z(); // 1
}

foo();
console.log(x); // 1

二、普通函数的this指向

1、默认绑定规则

  • 非严格模式下默认指向:window
  • 严格模式在指向:undefined
a();
function a () {
  console.log(this); // window
}
a();
function a () {
  'use strict';
  console.log(this); // undefined
}

2、隐式绑定规则

  • 谁调用,指向谁
function foo() {
  console.log(this.a);
}

var obj = {
  a: 2,
  foo: foo
}

obj.foo(); // 2

var bar = obj.foo;
bar(); // window.bar(); -> window上没有,则为undefined

3、显示绑定

  • call、apply、bind绑定

4、new

在new的时候将this转变成实例化的对象

  • new的时候改变了this指向

5、优先级:4>3>2>1

三、箭头函数

1、箭头函数写法

  • 说到箭头函数一定是箭头函数表达式(因为箭头函数没有函数名只能赋值给变量)
函数参数只有一个:括号可以省略
let f = a => { 
  return a;
}

// 相当于
let f = function(a) {
  return a;
}
函数体只return一个表达式:大括号可以省略,return可以省略
let f = a => a;

// 相当于
let f = function(a) {
  return a;
}
函数没有参数的话:括号不可以省略
let f = () => a;

// 相当于
let f = function() {
  return a;
}
函数体有多条语句: 括号不可省略
  • 箭头函数不指定返回值默认返回undefined
let f = function() {
  let a = 1,
      b = 2;

  console.log(a + b);
}

2、箭头函数结合函数参数的解构赋值

// 函数参数的解构赋值
const full = ({f, l} = {}) => f + '' + l;

function full({f, l} = {}) { // 相当于
  return f + '' + l;
}

console.log(full({f: 'l', l: 'yb'})); // lyb

3、箭头函数没有arguments

var sum = (a, b) => {
  console.log(arguments); //  arguments is not defined
}
sum();
  • 证明:=>function本质上是两个东西,不是function的简写

4、rest运算符(展开或者收集)

  • 箭头函数中arguments的替代品: …|spread|rest运算符
收集实参
// args: 随便定义,但是我们习惯使用args

var sum = (...args) => {
  console.log(args); // [1, 2]
}
sum(1, 2);
  • 拓展收集运算符必须是最后一位
let fn = (a, b, ...c) => {
  console.log(a, b, c);
}

// let fn = (...c, a, b) => { // 报错
//   console.log(a, b, c);
// }

fn(1, 2, 3, 4, 5, 6); // 1 2 [3, 4, 5, 6]
展开参数
function foo(a, b, c) {
  console.log(a, b, c);
}

foo(...[1, 2, 3]); // 1 2 3
  • 展开运算符实质是用apply实现的
function foo(a, b, c) {
  console.log(a, b, c);
  console.log(this);
}

foo.apply(null, [1, 2, 3]); // 1 2 3  window
foo.apply(undefined, [1, 2, 3]); // 1 2 3  window
  • 展开数组,并合并
let a = [1, 2, 3];
let b = [0, ...a, 4];
console.log(b); // [0, 1, 2, 3, 4]
函数中使用了 … 运算符,函数的长度将不再准确
console.log((function(a){}).length); // 1

console.log((function(...a){}).length); // 0

console.log((function(a, b, ...c){}).length); // 2

console.log((function(a, b = 1, ...c){}).length); // 1

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值