| Challenge 22 |
Essas propriedades você consegue acessar só se não executar a função. Nunca utilizar myFunc().name
, por exemplo.
Retorna o nome da função como uma string
. E se não usamos nome, se ela for anonima, retorna undefined
.
Conta quantos parâmetro a função pode receber. Importante por você poder validar uma função pela quantidade de parâmetros que estão sendo passados pra ela.
(function() {
'use strict';
function myFunc( a, b, c ) {
// lala código.
}
console.log( myFunc.lenght ); // retorna 3 no console
})();
Todos os objetos em JS têm uma propriedade toString
. E pra cada tipo de objeto o toString
funciona de uma forma diferente.
(function() {
'use strict';
var array = [ 1, 2, 3, 4 ];
console.log( array.toString() ); // retorna uma string: 1,2,3,4
})();
Quando utilizamos o toString
em um objeto, ele converte para [object Object]
(um objeto do tipo objeto)
(function() {
'use strict';
var obj = { prop1: 1, prop2: 2 };
console.log( obj.toString() ) // Retorna [object Object]
})();
Chamando o método baseado no valor da função( não executar a função!)
(function() {
'use strict';
function myFunc( a, b, c ) {
return 'oi';
}
console.log( myFunc.toString() );
/* retorna todo o corpo da função como string:
function myFunc( a, b, c ) {
return 'oi';
}
*/
})();
Invoca a função. É o mesmo que você usar myFunc()
.
(function() {
'use strict';
function myFunc( a, b, c ) {
return 'oi';
}
console.log( myFunc.call() ); // retorna: oi.
})();
Então pra quê usar o método call()
se eu posso chamar a função diretamente? Você pode passar um this
pra essa função: .call( this )
. Você pode dizer quem é o this
daquela função.
Um exemplo é quando temos uma função que tenha um construtor, e sabemos que quando usamos o new
em uma função (quando vamos criar um objeto baseado em um construtor/uma função que tenha um this
dentro dela) nós criamos um objeto que o this
fará a referência daquele novo objeto criado. Quando usamos o call, podemos dizer quem será o this
daquela função.
(function() {
'use strict';
function myFunc( a, b, c, d ) {
console.log( this.lastName );
}
var obj = {
lastName: 'Schmitz'
}
myFunc.call( obj ); // retorna; Schmitz
})();
Se você chamar o myFunc.call()
sem nada, retornará um erro:
"Uncaught TypeError: Cannot read property 'lastName' of undefined", porque o this.lastName
representa a window e na window não tem a propriedade lastName.
Quando você chama ela passando o obj como parâmetro myFunc.call(obj)
o obj será considerado o this da função! 😊
Além de você conseguir passar o this
, você também consegue passar argumentos para a função. Com a diferença que o primeiro parâmetro será o this
e os outros argumentos serão os parâmetros que a função pede: .call( this, arg1, arg2, ..., argN )
.
(function() {
'use strict';
function myFunc( a, b, c, d ) {
console.log( this.lastName, a, b, c, d );
}
var obj = {
lastName: 'Schmitz'
}
myFunc.call( obj, 'a', 'b', 'c', 'd' ); // retorna; Schmitz a b c d
// Posso passar só o this e 3 parâmetros, mas o ultimo retorna undefined:
myFunc.call( obj, 'a', 'b', 'c' ); // retorna; Schmitz a b c undefined
})();
Caso você não queira/não necessite passar o this, você passa null
no parâmetro que representa o this
. Além do null
(o null não é um objeto, mas representa um objeto por causa de um bug), você pode passar um objeto vazio {}
ou qualquer coisa que seja um objeto. Você pode passar também a própria função como this: myFunc.call( myFunc, 'a', 'b', 'c', 'd' );
.
Vamos supor que queremos o this
e os quatro parâmetros, porém quero fazer isso de forma dinâmica. Como vou quebrar o array para passar como parâmetro no call? Utilizando o apply
! Funcionamento extremamente parecido com o do .call()
a diferença é que com ele conseguimos passar como parâmetro o this
, um array ou um array-like. Quando usamos o apply cada item do array será 'quebrado' como um argumento da função.
(function() {
'use strict';
function myFunc( a, b, c, d ) {
console.log( this.lastName, a, b, c, d );
}
var obj = {
lastName: 'Schmitz'
}
var arr = [ 1, 2, 3, 4 ];
myFunc.apply( obj, arr ); // Schmitz 1 2 3 4
})();
Os principais objetos em JS (Object, String, Array, Date, RegExp, Number) têm uma propriedade chamada prototype
. Ela têm todos os métodos do nosso objeto principal que vamos herdar sempre que criarmos um novo objeto.
Ele é o protótipo dos nosssos métodos, dos nossos construtores e à partir dele conseguimos fazer herança no JS.
Ele será usado para estender nossos objetos.
Se colocarmos:
(function() {
'use strict';
function MyFunc( name, lastName ) {
this.name = name;
this.lastName = lastName;
}
MyFunc.fullName = function() {
return this.name + ' ' + this.lastName;
}
var eve = new MyFunc( 'Evelyn', 'Schmitz' );
console.log( eve.fullName() ); // Evelyn Schmitz
})();
Uncaught TypeError: eve.fullname is not a function => Porque eu não estou estendendo esse objeto, eu simplesmente criei um novo objeto e eu estou colocando em MyFunc
uma propriedade fullName
. Esse método será instanciado dentro de MyFunc e não do objeto que ele está criando. Nesse caso queremos que a função fullName seja uma propriedade do objeto que está sendo criado, a var eve
.
(function() {
'use strict';
function MyFunc( name, lastName ) {
this.name = name;
this.lastName = lastName;
}
MyFunc.prototype.fullName = function() {
return this.name + ' ' + this.lastName;
}
var eve = new MyFunc( 'Evelyn', 'Schmitz' );
console.log( eve.fullName() ); // Evelyn Schmitz
// Podemos criar propriedades depois de instanciar o meu objeto. Ex:
MyFunc.prototype.age = 30;
console.log( eve.age() ); // 30
// O prototype pode ser reescrito:
MyFunc.prototype.age = 20;
console.log( eve.age() ); // 20
})();
ATENÇÃO: Não esquecer o new
.
Se declararmos o this.age
direto dentro do objeto, ele não será sobrescrito porque propriedades do objeto se sobrepõem, são lidas antes das propriedades do protótipo. Como o JS faz essa leitura? Se eu chamei eve.age
, ele verifica se existe no objeto uma propriedade age
, caso exista é ela que vale, caso não exista ele verifica no protótipo do objeto se essa propriedade existe.
(function() {
'use strict';
function MyFunc( name, lastName ) {
this.name = name;
this.lastName = lastName;
this.age = 30;
}
MyFunc.prototype.fullName = function() {
return this.name + ' ' + this.lastName;
}
var eve = new MyFunc( 'Evelyn', 'Schmitz' );
console.log( eve.fullName() ); // Evelyn Schmitz
MyFunc.prototype.age = 20;
console.log( eve.age() ); // 30 porque propriedades do objeto(this.age = 30) se sobrepõem às propriedades do protótipo!
})();
O prototype é importante para nos ajudar entender como utilizar array-like como array.