JavaScript中的高阶函数并在EventEmitter的类中引用'this'关键字[重复]

Posted

技术标签:

【中文标题】JavaScript中的高阶函数并在EventEmitter的类中引用\'this\'关键字[重复]【英文标题】:Higher Order Functions in JavaScript and referring to the 'this' keyword within a class for an EventEmitter [duplicate]JavaScript中的高阶函数并在EventEmitter的类中引用'this'关键字[重复] 【发布时间】:2021-03-08 00:21:13 【问题描述】:

我已经在这个问题上停留了两天,并且在其他堆栈溢出帖子上没有骰子。我真的需要一些帮助。

我的目标是创建一个允许三个功能的事件发射器。订阅、取消订阅和 Emit - 其中,emit 将传递的参数发送到所有订阅函数。

我遇到的问题是我似乎无法将一个函数传递给订阅。我必须传递一个匿名函数来调用另一个函数。 subscribe(() => entities[1].eventEmitter.emit())subscribe(entities[1].eventEmitter.emit)。我似乎不明白这里的实际区别是什么,以及为什么他们会引用不同的“this”值。我认为第二个示例是第一个示例的简化版本?任何人都可以解释为什么两个版本引用不同的“this”值?

好吧,这一切都很好,因为传入匿名函数有效,但是当我尝试取消订阅时,我不再有对匿名函数的引用,因此无法从数组中删除它。我知道您可以将匿名函数存储在变量中,但这不可行,因为我动态生成这些实体并且可能存在“无限”实体。 IE。大小未知。

所以我一定是在这里做错了什么。要么我做错了,那里有一个更简单的解决方案,要么我只是错过了一些可以解决我的问题的东西。 Welcome 解决方案可以是完全不同的解决方案,也可以是成功订阅、取消订阅和发出的一种方式。谢谢!如果我可以提供更多说明,请告诉我。

class EventEmitter 
  constructor() 
    this.subscriptions = [];
  

  subscribe(fn) 
    this.subscriptions.push(fn);
  

  unsubscribe(fn) 
    this.subscriptions = this.subscriptions.filter(subscription => subscription !== fn);
  

  emit(args) 
    // upon subscribing, you should get an error when doing trigger that amounts to
    // "message": "Uncaught TypeError: Cannot read property 'subscriptions' of undefined"
    // this happens because the line entities[0].eventEmitter.subscribe(entities[1].eventEmitter.emit);
    // with argument passed in entities[1].eventEmitter.emit refers to the window?
    // so this.subscriptions is not defined
    // console.log(this);
    console.log('emitting');
    this.subscriptions.forEach(subscription => subscription(args));
  


class Entity 
  constructor()  
    this.eventEmitter = new EventEmitter();
  


const entities = [
  new Entity(),
  new Entity(),
];

document.getElementById('add').addEventListener('click', () => 
  // works, but requires an anonymous function that can't be removed
  entities[0].eventEmitter.subscribe(() => entities[1].eventEmitter.emit());
  
  // doesn't work because 'this' in the emit funciton refers to the window
  entities[0].eventEmitter.subscribe(entities[1].eventEmitter.emit);
, false);

document.getElementById('trigger').addEventListener('click', () => 
  entities[0].eventEmitter.emit();
, false);

document.getElementById('remove').addEventListener('click', () => 
  // how? ...
  // entities[0].eventEmitter.unsubscribe(entities[1].eventEmitter.emit);
, false);
<button id='add'>add event listener</button>
<button id='trigger'>trigger emit on element 0</button>
<button id='remove'>remove event listener</button>

【问题讨论】:

您可以将this.emit = this.emit.bind(this); 放入Entity 构造函数中,然后您可以在任何地方引用每个实体的方法并在其他地方订阅/取消订阅。 亲爱的主,它成功了!这是完美的,感谢您的帮助! 【参考方案1】:

嗯,您可以使用.bind() 并将其绑定到您的事件发射器类

我创建了一个存储方法的数组。

class EventEmitter 
  constructor() 
    this.subscriptions = [];
  

  subscribe(fn) 
    this.subscriptions.push(fn);
  

  unsubscribe(fn) 
    this.subscriptions = this.subscriptions.filter(subscription => subscription !== fn);
  

  emit(args) 
    // upon subscribing, you should get an error when doing trigger that amounts to
    // "message": "Uncaught TypeError: Cannot read property 'subscriptions' of undefined"
    // this happens because the line entities[0].eventEmitter.subscribe(entities[1].eventEmitter.emit);
    // with argument passed in entities[1].eventEmitter.emit refers to the window?
    // so this.subscriptions is not defined
    // console.log(this);
    this.subscriptions.forEach(subscription => 
       console.log("emit");
       subscription(args)
    );
  


class Entity 
  constructor()  
    this.eventEmitter = new EventEmitter();
  


const entities = [
  new Entity(),
  new Entity(),
];

let methods = [];

document.getElementById('add').addEventListener('click', () => 
 
 
  let method = entities[1].eventEmitter.emit.bind(entities[1].eventEmitter)
  methods.push(method);
  entities[0].eventEmitter.subscribe(method);
, false);

document.getElementById('trigger').addEventListener('click', () => 
  entities[0].eventEmitter.emit();
, false);

document.getElementById('remove').addEventListener('click', () => 
   entities[0].eventEmitter.unsubscribe(methods.pop())
, false);
<button id='add'>add event listener</button>
<button id='trigger'>trigger emit on element 0</button>
<button id='remove'>remove event listener</button>

【讨论】:

我会在早上跟进!凌晨 1 点在这里哈哈 感谢您的帮助!上面评论中的@Bergi 解决了我想要实现的目标!

以上是关于JavaScript中的高阶函数并在EventEmitter的类中引用'this'关键字[重复]的主要内容,如果未能解决你的问题,请参考以下文章

Javascript中的高阶函数介绍

JavaScript中的高阶函数

前端面试 JavaScript— 什么是高阶函数?数组中的高阶函数有哪些?

前端面试 JavaScript— 什么是高阶函数?数组中的高阶函数有哪些?

进阶 6-1 期JavaScript 高阶函数浅析

浅析javascript高阶函数