Javascript é uma linguagem orientada a protótipos então apesar de permitir a construção de objetos por meio de classes a partir do ECMAScript 2015, esta funcionalidade é apenas um syntax sugar
para funções construtoras.
Como o próprio nome define funções construtoras são funções que tem a capacidade de instanciar objetos. sua definição é como a de uma função normal no entanto dentro de seu contexto você pode utilizar a palavra reservada this
para acessar atributos e métodos.
function Person(name,surname){
this.name = name
this.surname = surname
this.toString = function(){return `${this.name} ${this.surname}`}
}
Para instanciar um objeto utilizando funções construtoras você deve utilizar a palavra reservada new
na chamada da função.
function Person(name,surname){
this.name = name
this.surname = surname
this.toString = function(){return `${this.name} ${this.surname}`}
}
const person = new Person("Ronnasayd","Machado")
console.log(person) // Person {name: "Ronnasayd", surname: "Machado", toString: ƒ}
console.log('nome completo: '+person) // nome completo: Ronnasayd Machado
Através da propriedade prototype
podemos adicionar novos métodos e atributos aos construtores existentes
function Person(name,surname){
this.name = name
this.surname = surname
this.toString = function(){return `${this.name} ${this.surname}`}
}
// se você tentar adicionar um método direto na função construtora não funcionará
Person.getAge = function(age){this.age = age}
const person = new Person("Ronnasayd","Machado")
person.getAge(27) // TypeError: person.getAge is not a function
// você deve usar a propriedade prototype para tal adição
Person.prototype.getAge = function(age){this.age = age}
const person = new Person("Ronnasayd","Machado")
person.getAge(27)
console.log(person) // Person {name: "Ronnasayd", surname: "Machado", age: 27, toString: ƒ}
Outra forma de criar objetos em javascript é através de objetos literais que consiste na criação de um par de chaves tendo atributos e métodos separados por virgulas no seu interior. Cada atributo ou método é criado em um modelo de chave e valor similar ao JSON
const person = {name:"Ronnasayd",surname:"Machado"}
console.log(person) // {name: "Ronnasayd", surname: "Machado"}
Todo objeto literal é um objeto único e, mesmo que você armazene ele em diferentes variáveis todas apontarão para o mesmo objeto. Seu uso é recomendado em situações onde não podem existir mais de uma instância do objeto, como por exemplo, objetos de configurações do projeto ou coleções de objetos
const person = {name:"Ronnasayd",surname:"Machado"}
console.log(person) // {name: "Ronnasayd", surname: "Machado"}
const person2 = person
person2.name = "João"
console.log(person) // {name: "João", surname: "Machado"}
A palavra reservada this
é comumente utilizada em linguagens de alto nível que adotam o paradigma de orientação a objetos, para referenciar a instância da classe e assim ter acesso a seus atributos e métodos. Javascript porém é uma linguagem voltada a protótipos, então apesar de termos acesso a essa palavra, seu contexto é variável e pode assumir assim diferentes valores dependendo de onde é utilizada
Em um método refere-se ao objeto a qual pertence
const person = {
name : 'Ronnasayd',
surname : 'Machado',
toString: function(){return `${this.name} ${this.surname}`}
}
console.log('nome completo: ' + person) // nome completo: Ronnasayd Machado
Sozinho refere-se ao objeto global
// No navegador retornará uma referência para window que é o objeto global.
// Em NodeJS retornará uma referência para o objeto global
console.log(this)
Em uma função refere-se ao objeto global
function printGlobalObject(){
console.log(this)
}
printGlobalObject()
Em uma função em strict mode
é undefined
function printGlobalObject(){
'use strict'
console.log(this) // undefined
}
printGlobalObject()
Em um evento refere-se ao elemento que recebe o evento
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<button id="button">Me clica!!!</button>
</body>
<script>
const { button } = window;
button.addEventListener("click", function (event) {
this.innerText = "Agora estou grande!!!";
this.style.background = "red";
this.style.color = "white";
this.style.padding = "10px";
this.style.fontWeight = "bold";
this.style.fontSize = "16px";
});
</script>
</html>
call
, bind
e apply
são métodos que permitem especificar o contexto de this
dentro de uma função. elas permitem que você injetem um objeto/valor que será o novo contexto. No entanto a chamada e a forma como fazem isso diferem.
O método call
invoca uma função com um dado valor this
e argumentos passados individualmente.
function time(complement){
return `${this.name} é ${this.description} ${complement}`
}
const flamengo={
name:"Flamengo",
description:"atual campeão brasileiro"
}
phrase = time.call(flamengo,"tendo ganho os campeonatos 2019/2020")
console.log(phrase) // Flamengo é atual campeão brasileiro tendo ganho os campeonatos 2019/2020
O método apply
chama uma função com um dado valor this
e argumentos providos como um array
function logs(...descriptions){
descriptions.forEach(description=>{
this.logs.push(`${new Date().toISOString()}: ${description}`)
})
}
const logsRegister = {
logs:[]
}
logs.apply(logsRegister,[
"Abriu documento",
"Escreveu no documento",
"Fechou o documento"
])
console.log(logsRegister) // {logs: Array(3)}
Ao contrário dos outros, o método bind
não executa uma função, mas retorna uma outra com um novo contexto. O primeiro argumento recebe o valor do this
a ser usado na função, e os demais argumentos são os parâmetros que terão valores atribuídos dentro da mesma.
function time(complement){
return `${this.name} é ${this.description} ${complement}`
}
const flamengo={
name:"Flamengo",
description:"atual campeão brasileiro"
}
phrase = time.bind(flamengo,"tendo ganho os campeonatos 2019/2020")
console.log(phrase) // ƒ time(complement){return `${this.name} é ${this.description} ${complement}`}
console.log(phrase()) // Flamengo é atual campeão brasileiro tendo ganho os campeonatos 2019/2020
como vocês devem ter percebido esses 3 métodos podem ser utilizados em funções construtoras para reaproveitar código através herança
function Product(name, price) {
this.name = name;
this.price = price;
}
function Food(name, price) {
Product.call(this, name, price);
this.category = 'food';
}
const food = new Food('cheese', 5)
console.log(food.name) // cheese