Skip to content

Instantly share code, notes, and snippets.

@AlyoshaS
Last active July 10, 2018 05:15
Show Gist options
  • Save AlyoshaS/9c2fd46713bbc03ba3cf1de6fba0e0c6 to your computer and use it in GitHub Desktop.
Save AlyoshaS/9c2fd46713bbc03ba3cf1de6fba0e0c6 to your computer and use it in GitHub Desktop.

Anotações JS

| Challenge 22 |

Propriedades e métodos das funções

Essas propriedades você consegue acessar só se não executar a função. Nunca utilizar myFunc().name, por exemplo.

Propriedade .name

Retorna o nome da função como uma string. E se não usamos nome, se ela for anonima, retorna undefined.

Propriedade .length

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
})();

Propriedade .toString

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';
    }
    */
})();

Método .call()

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! 😊

.call( this, arg1, arg2, ..., argN )

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' );.

Método .apply( this, [ arg1, arg2, ..., argN ])

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
})();

Método .prototype

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.

Array-Like Como Array

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment