TypeScript 经典函数与箭头方法

何时使用不同的符号。

经典函数和箭头方法非常相似,但语法不同。

从 ES2015 开始,有一种箭头函数语法可用:它具有轻量级语法,并且使用匿名函数而无需显式返回。

const result = (person) => {
  return `Good afternoon, ${person}`;
}
// RxJs method "find" which looks for records in array:
const preSelectedTariff = this._tariffs?.find(tariff => tariff.tariffUniqueId === this.selectedTariff?.tariffUniqueId);

Lambda 是一个小型匿名函数。 它可以接受任意数量的参数,但只能有一个表达式。 但是匿名会产生一些问题:

1. 更难调试

当我们收到错误时,我们将无法跟踪函数的名称或发生错误的确切行号。

2. 块作用域

在逻辑上与经典函数一起工作。 函数可以按任何顺序声明,应用程序将以任何方式工作。

callMyFunction();
function callMyFunction() {
  console.log(`Rnd number ${getAnother(1000)}`);
}
function getAnother(max: number) {
  return Math.floor(Math.random() * (max + 1));
}

这是命令式编程与函数式编程。 他们每个人都有自己的优势。 但是由于块作用域,函数应该按照它们出现的顺序来声明。

tryToCallInWrongOrder();
const tryToCallInWrongOrder = () => {
  console.log(`Trying to call the function ${getAnother(1001)}`);
}
function getAnother(max: number) {
  return Math.floor(Math.random() * (max + 1));
}

3. 没有自引用

如果我们的函数需要具有自引用,那么它将不起作用。 例如,它可以是递归或事件处理程序。


不应该使用 箭头方法的场景:

1. 对象里的方法

当我们在对象内部使用箭头函数时,它从外部范围继承 this 值,而不是从本地范围, 并且 count 变量不可用。

const counter = {
  count: 0,
  getFollowing: () => this.count+1,
  getCurrent: () => this.count
};
console.log( counter.getFollowing() );

在 JavaScript 中:使用 arguments 对象的函数。

箭头函数没有参数对象。 因此,如果我们有一个使用 arguments 对象的函数,则不能使用箭头函数。

const concat = (separator) => {
    let args = Array.prototype.slice.call(arguments, 1);
    return args.join(separator);
}

但是参数在常规函数中起作用:

function getChar() {
  return Array.prototype.slice.call(arguments,0,1);
}
console.log(getChar('a','b','c'));
// 或使用这样的分隔符:
function concat(separator) {
    let args = Array.prototype.slice.call(arguments, 2);
    return args.join(separator);
}
console.log( concat(',', 'A', 'B', 'C', 'D', 'E') );

当它使我们的代码难以理解时

常规函数提供 100% 清晰的输入参数和输出类型语法。 但是箭头方法对于输入类型和输出内容并不那么简单。 它是函数式编程方法。


该方法的两种符号之间的好处区别是什么?

1. 继承

箭头方法不允许在子类中继承相同的方法,它不会被覆盖。

class Parent {
  method = () => { console.log("Parent method"); }
}
class Child extends Parent {
  method = () => {  // 不会覆盖 Parent 方法
    super.method();
    // 不起作用,因为引用了不存在的 Parent.prototype.method
  }
}

2. new

常规函数是可构造的,可以使用 new 关键字调用它们。

const kv = new Map();

kv.set("Test msg", "Unknown");
kv.set("", "Unknown");
kv.set(null, "Unknown");
kv.forEach((value, key) => {
  expect(new RequestTypePipe().transform(key)).toEqual(value);
});

但是,箭头函数永远不能用作构造函数。 因此,它们永远不能用 new 关键字调用:

let add = (x: number, y: number) => console.log(x + y);
const error = new add(1, 1); // TypeError: 'add' is not a constructor
const result = add(1000, 1);

new 关键字提供了创建实例的清晰方法:

private readonly unsubscribe$: Subject<void> = new Subject();
private chargeSubscription: Subscription;
ngOnDestroy(): void {
  this.unsubscribe$.next();
  this.unsubscribe$.complete();
}
private readonly subscribeToQuotation = (): void => {
  this.chargeSubscription = this.myService()
    .pipe(takeUntil(this.unsubscribe$))
    .subscribe(charge => this.handleCharge(charge));
};

3. 参数绑定

const mapToLocationCode = (geo: Geo): string => geo?.code || "";
return mapToLocationCode(houseObject.geo);

但是,如果要访问箭头函数中的参数,可以使用 rest 运算符:

var arrowFunction = (...args) => {
    console.log(...args)
}
arrowFunction("my", "additional", "argument");

4. 隐式返回

经典函数使用 return 关键字来返回值。 如果错过了,则该函数将返回未定义。

箭头函数减少代码,提供隐式返回,使代码更干净。

let message = () => 1001;
const result = (message: () => void) => { console.log(message) };
// 将message 作为参数传给result方法
result(message); 

这来自 Kotlin 世界:如果没有参数 – 使用下划线:

let myArrowMethod = _ => console.log("Arrow Method");

5. this

ES6 箭头方法没有 this,不能绑定 this 关键字。 我们所能做的就是引用外部范围变量。

const thename = "Alex";
let nameObject = {
  name : "Another Alex",
  arrowMethod: () => {
    console.log('arrowFunc: ' + thename);  //access to outer variabl
  },
  classicFunction() {
    console.log('classicFunction: ' + this.name); 
  }   
}
nameObject.arrowMethod();
nameObject.classicFunction();

常规函数用自己的 this 定义创建一个对象和一个作用域,但与箭头方法不同。

let currentValue: { value: string };
// 经典函数
const saveFunction = function (data: any) {
  currentValue = { 'value': data };
  console.log(currentValue);
}
// 箭头函数
const arrowMethod = (data: any) => {
  currentValue = { 'value': data };
  console.log(currentValue);
}
saveFunction('method');
arrowMethod('arrow');

总结

还有很多其他的差异,我描述了其中的主要差异。 很难说,何时选择其中一种方法。 函数式编程需要更少的代码,经常使用箭头方法!

免责声明:
1.本站所有内容由本站原创、网络转载、消息撰写、网友投稿等几部分组成。
2.本站原创文字内容若未经特别声明,则遵循协议CC3.0共享协议,转载请务必注明原文链接。
3.本站部分来源于网络转载的文章信息是出于传递更多信息之目的,不意味着赞同其观点。
4.本站所有源码与软件均为原作者提供,仅供学习和研究使用。
5.如您对本网站的相关版权有任何异议,或者认为侵犯了您的合法权益,请及时通知我们处理。
火焰兔 » TypeScript 经典函数与箭头方法