quiz/js: difference between function declaration, function call, and constructor call (#442)
This commit is contained in:
parent
f2b326c982
commit
87674b2103
|
|
@ -2,11 +2,35 @@
|
|||
title: 'Difference between: `function Person(){}`, `var person = Person()`, and `var person = new Person()`?'
|
||||
---
|
||||
|
||||
This question is pretty vague. Our best guess at its intention is that it is asking about constructors in JavaScript. Technically speaking, `function Person(){}` is just a normal function declaration. The convention is to use PascalCase for functions that are intended to be used as constructors.
|
||||
## TL;DR
|
||||
|
||||
`var person = Person()` invokes the `Person` as a function, and not as a constructor. Invoking as such is a common mistake if the function is intended to be used as a constructor. Typically, the constructor does not return anything, hence invoking the constructor like a normal function will return `undefined` and that gets assigned to the variable intended as the instance.
|
||||
- `function Person(){}`: A function declaration in JavaScript. It can be used as a regular function or as a constructor.
|
||||
- `var person = Person()`: Calls `Person` as a regular function, not a constructor. If Person is intended to be a constructor, this will lead to unexpected behavior.
|
||||
- `var person = new Person()`: Creates a new instance of `Person`, correctly utilizing the constructor function to initialize the new object.
|
||||
|
||||
`var person = new Person()` creates an instance of the `Person` object using the `new` operator, which inherits from `Person.prototype`. An alternative would be to use `Object.create`, such as: `Object.create(Person.prototype)`.
|
||||
| Aspect | `function Person(){}` | `var person = Person()` | `var person = new Person()` |
|
||||
|------------------|-----------------------|---------------------------------------------|-----------------------------------|
|
||||
| Type | Function declaration | Function call | Constructor call |
|
||||
| Usage | Defines a function | Invokes `Person` as a regular function | Creates a new instance of `Person`|
|
||||
| Instance Creation| No instance created | No instance created | New instance created |
|
||||
| Common Mistake | N/A | Misusing as constructor leading to undefined| None (when used correctly) |
|
||||
|
||||
---
|
||||
|
||||
## Function declaration
|
||||
|
||||
`function Person(){}` is a standard function declaration in JavaScript. When written in PascalCase, it follows the convention for functions intended to be used as constructors.
|
||||
|
||||
```js
|
||||
function Person(name) {
|
||||
this.name = name;
|
||||
}
|
||||
```
|
||||
This code defines a function named `Person` that takes a parameter `name` and assigns it to the `name` property of the object created from this constructor function. When the `this` keyword is used in a constructor, it refers to the newly created object.
|
||||
|
||||
## Function call
|
||||
|
||||
`var person = Person()` simply invoke the function's code. When you invoke `Person` as a regular function (i.e., without the `new` keyword), the function does not behave as a constructor. Instead, it executes its code and returns `undefined` if no return value is specified and that gets assigned to the variable intended as the instance. Invoking as such is a common mistake if the function is intended to be used as a constructor.
|
||||
|
||||
```js
|
||||
function Person(name) {
|
||||
|
|
@ -16,8 +40,36 @@ function Person(name) {
|
|||
var person = Person('John');
|
||||
console.log(person); // undefined
|
||||
console.log(person.name); // Uncaught TypeError: Cannot read property 'name' of undefined
|
||||
```
|
||||
In this case, `Person('John')` does not create a new object. The `person` variable is assigned `undefined` because the `Person` function does not explicitly return a value. Attempting to access `person.name` throws an error because `person` is `undefined`.
|
||||
|
||||
## Constructor call
|
||||
|
||||
`var person = new Person()` creates an instance of the `Person` object using the new operator, which inherits from `Person.prototype`. An alternative would be to use `Object.create`, such as: `Object.create(Person.prototype)` and `Person.call(person, 'John')` initializes the object.
|
||||
|
||||
```js
|
||||
function Person(name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
var person = new Person('John');
|
||||
console.log(person); // Person { name: "John" }
|
||||
console.log(person.name); // "john"
|
||||
console.log(person); // Person { name: 'John' }
|
||||
console.log(person.name); // 'John'
|
||||
|
||||
// Alternative
|
||||
var person1 = Object.create(Person.prototype);
|
||||
Person.call(person1, 'John');
|
||||
console.log(person1); // Person { name: 'John' }
|
||||
console.log(person1.name); // 'John'
|
||||
```
|
||||
In this case, `new Person('John')` creates a new object, and `this` within `Person` refers to this new object. The `name` property is correctly set on the new object. The `person` variable is assigned the new instance of `Person` with the name property set to `'John'`. And for the alternative object creation, `Object.create(Person.prototype)` creates a new object with `Person.prototype` as its prototype. `Person.call(person, 'John')` initializes the object, setting the `name` property.
|
||||
|
||||
## Follow-Up Questions
|
||||
|
||||
- What are the differences between function constructors and ES6 class syntax?
|
||||
- What are some common use cases for Object.create?
|
||||
|
||||
## Further reading
|
||||
- [MDN Web Docs: Object prototypes](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Object_prototypes)
|
||||
- [Differences between Class and Function Constructors](https://www.greatfrontend.com/questions/quiz/what-are-the-differences-between-es6-class-and-es5-function-constructors)
|
||||
- [How `this` keyword works in JavaScript?](https://www.greatfrontend.com/questions/quiz/explain-how-this-works-in-javascript)
|
||||
|
|
|
|||
Loading…
Reference in New Issue