Angular 6 : Use of access modifier while injection

2020-07-23 06:38发布

问题:

While going through the tutorial, i am coming across a strange scenario.

while injecting the service in your component if you miss the access modifier it will give you error as given below, but adding it as private or public will run fine.

Dont we have any default scope in Angular if we miss the access modifier ?

export class UserDetailsComponent implements OnInit {

  name="";
  lastName="";
  constructor(userService : UserServiceService) { }

  ngOnInit() {
  }

  save(){
    this.userService.saveUser();

  }

}

Property 'userService' does not exist on type 'UserDetailsComponent'.

回答1:

If you prefix a constructor parameter with an access modifier (private, protected or public) or readonly, it automatically gets "promoted" to be a class property in TypeScript. This construct is referred to as constructor parameter properties.

Without the prefix, the constructor parameter is nothing more than a method parameter, and you would have to manually assign it to a declared class property from the constructor itself.

From the handbook:

Parameter properties are declared by prefixing a constructor parameter with an accessibility modifier or readonly, or both. Using private for a parameter property declares and initializes a private member; likewise, the same is done for public, protected, and readonly.



回答2:

All of the answers already provided are very clear and have good info. So to put things in a simple way, here is what is happening:

Your constructor is a function. In any programming language (that I've come across so far) a function's parameters only exist within the scope of the function itself. So the parameter being passed in the constructor is not available throughout the class unless its value is explicitly assigned to a class member (as seen in the second piece of code provided by Samuel J Matthew.

What the access modifiers in the parameter do is they instruct Angular to create a class member of the same name as the parameter, with the provided access modifier, and initialize it to an instance of the parameter type. In other words, the parameter becomes a class member/property. As has already been said, this is called a parameter property, which is a very fitting name for it.

The documentation provided by Ken is very helpful. Definitely worth reading.



回答3:

Typescript provides a shortcut for you for a common pattern for dependency injection.

You can either put this in your constructor:

  this.userService = userService

And also create a property declaration:

  userService: UserService;

Or, you can just put ‘public’ on the ctor function parameter and Typescript does all that for you. The same works for ‘private’. But AOT may fail if try to use a private property in your template.

More info



回答4:

The problem occurs when you are not providing any access specifier for the parameters of constructor it will not get registered at class level.Instead the scope of the parameter variable limited to the constructor function.In order to make it available across the class we give the access modifiers

With your example

export class UserDetailsComponent implements OnInit {
  name="";
  lastName="";
  constructor(userService : UserServiceService) {
    console.log(userService)
  }
  ngOnInit() {
  }
  save(){
    this.userService.saveUser();
  }
}

the userService is only available inside constructor If you place a console.log(userService) inside constructor you may get some console output.

If you don't want to specify any access modifiers or want to assign to a another class variable you can specify like following

export class UserDetailsComponent implements OnInit {
  name="";
  lastName="";
  private _service
  constructor(userService : UserServiceService) { 
    this._service = userService;
  }
  ngOnInit() {
  }
  save(){
    this._service.saveUser();
  }
}

In the above code i had assigned the injected userService to another class member _service