Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
我是否应该在Angular';s级_Angular_Typescript_Ecmascript 6 - Fatal编程技术网

我是否应该在Angular';s级

我是否应该在Angular';s级,angular,typescript,ecmascript-6,Angular,Typescript,Ecmascript 6,在Angular中,将类方法编写为ES2015 arrow函数在技术上是可能的,但我从未见过有人这样做。以这个简单的组件为例: @Component({ selector: 'sample' }) export class SampleComponent { arrowFunction = param => { // Do something }; normalFunction(param) { // Do something } } 这样做没有任何问

在Angular中,将类方法编写为ES2015 arrow函数在技术上是可能的,但我从未见过有人这样做。以这个简单的组件为例:

@Component({
  selector: 'sample'
})
export class SampleComponent {
  arrowFunction = param => {
    // Do something
  };
  normalFunction(param) {
    // Do something
  }
}

这样做没有任何问题。有什么不同吗?为什么我应该或者不应该使用这个呢?

类箭头函数的一个很好的使用案例是,当您想将一个函数传递给另一个组件,并在函数中保存当前组件的上下文时

@Component({

   template:`
        I'm the parent
       <child-component></child-component>

  `
})
export class PerentComponent{

   text= "default text"
   arrowFunction = param => {
    // Do something
    // let's update something in parent component ( this)

    this.text = "Updated by parent, but called by child"
  };
}

@Component({

   template:`
        I'm the child component

  `
})
export class ChildComponent{
   @Input() parentFunction;

   ngOnInit(){
      this.parentFunction.()
   }
}

 <parent-component></parent-component>

有一种情况是,如果需要进行AOT编译,就必须避免使用箭头函数,如文档所示

配置模块时,不能使用箭头功能

❌ 不要:

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { Routes, RouterModule } from '@angular/router';

@NgModule({
  imports: [
    BrowserModule,
    RouterModule,
    HttpModule,
    RouterModule.forRoot([], { errorHandler: (err) => console.error(err) })
  ],
  bootstrap: [
    AppComponent
  ],
  declarations: [
    AppComponent
  ]
})
export class AppModule {}
✅ 做:

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { Routes, RouterModule } from '@angular/router';

function errorHandler(err) {
  console.error(err);
}

@NgModule({
  imports: [
    BrowserModule,
    RouterModule,
    HttpModule,
    RouterModule.forRoot([], { errorHandler })
  ],
  bootstrap: [
    AppComponent
  ],
  declarations: [
    AppComponent
  ]
})
export class AppModule {}
中的要点在Angular、任何其他框架或普通JavaScript/TypeScript中仍然有效

类原型方法是ES6,类箭头方法不是。箭头方法属于而不是现有规范的一部分。它们是用TypeScript实现的,也可以用Babel传输

通常,使用prototype
method(){…}
比使用arrow
method=()=>{…}
更为可取,因为它更灵活

回调 arrow方法提供的唯一真正机会是它可以无缝地用作回调:

class Class {
  method = () => { ... }
}

registerCallback(new Class().method);
如果原型方法应用作回调,则应另外绑定,最好在构造函数中完成:

class Class {
  constructor() {
    this.method = this.method.bind(this);
  }

  method() { ... }
}

registerCallback(new Class().method);
import bind from 'bind-decorator';

class Class {
  @bind
  method() { ... }
}
可以在TypeScript和ES Next中使用类似于decorator的函数,为构造函数中的方法绑定提供更简洁的替代方法:

class Class {
  constructor() {
    this.method = this.method.bind(this);
  }

  method() { ... }
}

registerCallback(new Class().method);
import bind from 'bind-decorator';

class Class {
  @bind
  method() { ... }
}
遗产 Arrow方法限制子类也使用Arrow方法,否则它们不会被重写。如果忽略箭头,则会产生问题:

class Parent {
  method = () => { ... }
}

class Child extends Parent {
  method() { ... } // won't override Parent method
}
无法在子类中使用
super.method()
,因为
super.method
引用的是
Parent.prototype.method
,它不存在:

class Parent {
  method = () => { ... }
}

class Child extends Parent {
  method = () => {
    super.method(); // won't work
    ...
  }
}
混血儿 原型方法可以有效地用于混合。mixin对于多重继承或修复TypeScript方法可见性中的问题非常有用

由于arrow方法在类原型上不可用,因此无法从类外部访问它:

class Parent {
  method = () => { ... }
}

class Child extends OtherParent { ... }
Object.assign(Child.prototype, Parent.prototype) // method won't be copied
测试 原型方法提供的一个有价值的特性是,它们在类实例化之前是可访问的,因此它们可以在测试中被监视或模拟,即使它们在构造之后被调用:

class Class {
  constructor(arg) {
    this.init(arg);
  }

  init(arg) { ... }
}

spyOn(Class.prototype, 'init').and.callThrough();
const object = new Class(1);
expect(object.init).toHaveBeenCalledWith(1);
当方法是箭头时,这是不可能的


TL;DR:在prototype和arrow类方法之间进行选择似乎是一个品味问题,但实际上prototype方法的使用更具远见。通常,您可能希望避免使用arrow类方法,除非您确信它们不会造成不便。如果您将原型方法作为回调传递,请不要忘记在原型方法上使用
bind

伙计,我投了更高的票,但您确实在这里再次改写了答案:)@Milad这是一个非常流行的问题,而之前的问题太窄了。我试图解决所有的问题并给出一个规范的答案。是的,主要的观点仍然存在,因为他们必须。真棒的答案!非常好的答案,但在你的TL;DR,您不一定需要使用.bind如果在类本身内部使用胖箭头调用基于原型的方法?@RichardWatts这是正确的,您不需要在这里使用
bind
。但是使用诸如
.subscribe(this.myMethod)
之类的绑定方法是有益的,因为1)您不需要枚举arg,特别是如果有多个arg(并且
(…args)=>myMethod(…args)
不适合TS类型)2)如果经常调用这段代码,您不需要每次调用时都创建箭头函数3)这有助于单元测试,您可以断言
expect(obs.subscribe).toHaveBeenCalledWith(obj.myMethod)
——这是匿名函数无法做到的。除此之外,arrow还可以。正如本文中提到的,这似乎只适用于模块配置期间,这表明arrow作为类方法的功能对于AOT是可以的。