JavaScript箭头函数、this绑定

目录

箭头函数

一、基本语法

1. 单参数,单表达式

2. 无参数或多参数

3. 多行函数体

4. 返回对象字面量

二、箭头函数 vs 传统函数

三、核心特性

1. 词法作用域的 this

2. 没有 arguments 对象

3. 不能作为构造函数

4. 不适合作为对象方法

四、适用场景

五、注意事项

六、总结

显式绑定函数的this指向

一、核心作用

二、语法与参数对比

三、详细解析与示例

1. call

2. apply

3. bind

四、应用场景

1. 借用其他对象的方法

2. 实现函数柯里化(Currying)

3. 组合继承(构造函数继承)

五、注意事项

1. 箭头函数的 this 不可变

2. null 或 undefined 作为 thisArg

六、总结


箭头函数

JavaScript 的 箭头函数(Arrow Functions) 是 ES6 引入的重要特性,它简化了函数写法并改变了 this 的绑定规则。


一、基本语法

箭头函数用更简洁的方式定义函数,语法如下:

1. 单参数,单表达式
// 传统函数
const add = function(a, b) { return a + b; };

// 箭头函数(省略 return 和 {})
const add = (a, b) => a + b; 
2. 无参数或多参数
// 无参数
const sayHi = () => console.log('Hi!');

// 多参数(必须加括号)
const multiply = (a, b) => a * b;
3. 多行函数体
const sumAndLog = (a, b) => {
  const result = a + b;
  console.log(result);
  return result;
};
4. 返回对象字面量

需用 () 包裹对象,避免 {} 被解析为函数体:

const createUser = (name) => ({ name: name, age: 30 });

示例:

const numbers = [1, 2, 3]
const doubledEvens = numbers
  .filter(num => num % 2 === 0)
  .map(num => num * 2);

二、箭头函数 vs 传统函数

特性箭头函数传统函数
this 绑定词法作用域(定义时决定)动态作用域(调用时决定)
构造函数不可用(无 prototype可用
arguments 对象
生成器函数不可用(无法用 yield可用
方法定义慎用(this 可能不符预期)推荐

三、核心特性

1. 词法作用域的 this

箭头函数没有自己的 this,它会捕获定义时的外层作用域的 this,且无法通过 callapplybind 修改。

示例

const obj = {
  name: "Alice",
  traditionalFunc: function() {
    console.log(this.name); // "Alice"(this 指向 obj)
  },
  arrowFunc: () => {
    console.log(this.name); // undefined(this 指向外层,此处为全局)
  }
};
obj.traditionalFunc();
obj.arrowFunc();

适用场景:回调函数中保留外层 this

// 传统函数需要额外绑定 this
button.addEventListener('click', function() {
  console.log(this); // button 元素
});

// 箭头函数继承外层 this
class App {
  constructor() {
    this.data = "Hello";
    button.addEventListener('click', () => {
      console.log(this.data); // "Hello"(this 指向 App 实例)
    });
  }
}

2. 没有 arguments 对象

箭头函数无法通过 arguments 访问参数列表,需改用 剩余参数(Rest Parameters):

const showArgs = (...args) => {
  console.log(args); // 参数数组
};
showArgs(1, 2, 3); // [1, 2, 3]

3. 不能作为构造函数

箭头函数没有 prototype 属性,使用 new 调用会报错:

const Person = () => {};
const p = new Person(); // 报错:Person is not a constructor

4. 不适合作为对象方法

箭头函数作为对象方法时,this 不会指向对象本身:

const counter = {
  count: 0,
  increment: () => {
    this.count++; // this 指向全局,而非 counter
  }
};
counter.increment();
console.log(counter.count); // 0(未改变)

解决方法:使用传统函数或直接定义:

const counter = {
  count: 0,
  increment() { // 传统方法简写
    this.count++;
  }
};

四、适用场景

  1. 简短的匿名函数

    const numbers = [1, 2, 3];
    const doubled = numbers.map(n => n * 2);
  2. 需要固定 this 的回调

    class Timer {
      constructor() {
        this.seconds = 0;
        setInterval(() => {
          this.seconds++; // this 指向 Timer 实例
        }, 1000);
      }
    }
  3. 函数式编程(如 reducefilter

    const sum = [1, 2, 3].reduce((acc, num) => acc + num, 0);

五、注意事项

  1. 避免过度简写
    复杂的逻辑仍需使用 {} 和明确 return 以提高可读性。

  2. 慎用箭头函数作为方法
    对象方法、原型方法中优先使用传统函数。

  3. 不存在函数提升
    箭头函数属于表达式函数,因此不存在函数提升。

  4. 无法用于动态 this 的场景
    如 DOM 事件回调需要访问事件目标时:

    button.addEventListener('click', (e) => {
      console.log(this); // 外层 this(可能不符合预期)
      console.log(e.target); // 正确获取目标元素
    });

六、总结

  • 箭头函数:简洁、固定 this,适合回调、函数式编程。

  • 传统函数:动态 this,适合构造函数、对象方法、需要 arguments 的场景。

  • 选择依据:根据 this 的需求、上下文和使用场景合理选择。


   

显式绑定函数的this指向

一、核心作用

callapply 和 bind 用于 显式绑定函数的 this 指向,并支持传递参数,是 JavaScript 中灵活控制函数上下文的核心方法。


二、语法与参数对比

方法语法参数传递方式执行方式
callfunc.call(thisArg, arg1, arg2...)逐个传递参数立即执行函数
applyfunc.apply(thisArg, [argsArray])数组形式传递参数立即执行函数
bindfunc.bind(thisArg, arg1, arg2...)逐个传递参数返回新函数,需调用

三、详细解析与示例

1. call

  • 作用:立即调用函数,指定 this 并逐个传递参数。

  • 示例

    function greet(greeting, punctuation) {
      console.log(`${greeting}, ${this.name}${punctuation}`);
    }
    
    const person = { name: 'Alice' };
    
    greet.call(person, 'Hello', '!'); // "Hello, Alice!"

2. apply

  • 作用:立即调用函数,指定 this 并以数组形式传递参数。

  • 典型场景:处理数组参数(如 Math.max)。

    const numbers = [5, 6, 2, 3, 7];
    
    // 使用 apply 展开数组作为参数
    const max = Math.max.apply(null, numbers); // 7
    
    // ES6 中可用扩展运算符替代
    const maxEs6 = Math.max(...numbers); // 7

3. bind

  • 作用:返回一个绑定了 this 和预设参数的新函数,需手动调用。

  • 典型场景:事件回调、异步操作中固定上下文。

    const person = {
      name: 'Bob',
      sayHi: function() {
        console.log(`Hi, ${this.name}!`);
      }
    };
    
    const boundSayHi = person.sayHi.bind(person);
    setTimeout(boundSayHi, 100); // "Hi, Bob!"(而非全局 this)

四、应用场景

1. 借用其他对象的方法
// 类数组对象借用数组方法
const arrayLike = { 0: 'a', 1: 'b', length: 2 };

// 使用 Array.prototype.push
Array.prototype.push.call(arrayLike, 'c');
console.log(arrayLike); // {0: 'a', 1: 'b', 2: 'c', length: 3}
2. 实现函数柯里化(Currying)
function multiply(a, b) {
  return a * b;
}

// 固定第一个参数为 2
const double = multiply.bind(null, 2);
console.log(double(5)); // 10
3. 组合继承(构造函数继承)
function Parent(name) {
  this.name = name;
}
Parent.prototype.sayName = function() {
  console.log(this.name);
};

function Child(name, age) {
  Parent.call(this, name); // 继承属性
  this.age = age;
}

// 继承方法
Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child;

const child = new Child('Charlie', 10);
child.sayName(); // "Charlie"

五、注意事项

1. 箭头函数的 this 不可变

箭头函数的 this 由词法作用域决定,无法通过 call/apply/bind 修改:

const obj = {
  value: 42,
  getValue: () => this.value // this 指向外层(如 window)
};

console.log(obj.getValue.call({ value: 100 })); // undefined
2. null 或 undefined 作为 thisArg

当 thisArg 为 null 或 undefined 时,非严格模式下 this 指向全局对象(如 window),严格模式下为 null/undefined


六、总结

方法核心特性适用场景
call立即执行,参数逐个传递明确参数个数时
apply立即执行,参数数组传递参数动态或为数组时
bind返回新函数,延迟执行需要固定上下文或预设参数的场景

关键记忆点

  • call 和 apply:立即执行,参数形式不同。

  • bind:延迟执行,返回新函数。

  • 箭头函数:无法改变 this,慎用这三个方法。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值