Percursos
/
JavaScript
JavaScript
/
Exercícios
/
Robot de reciclagem
Robot de reciclagem

Robot de reciclagem

Exercício de aprendizagem

Introdução

Saber qual é o tipo de um dado é, muitas vezes, muito importante para que o código corra sem problemas e sem erros.

O JavaScript tem várias formas de verificar o tipo de um valor ou de um objeto.

Note

Os mecanismos de verificação de tipos do JavaScript nem sempre são fiáveis.

Para uma melhor segurança de tipos e tipos mais fortes, provavelmente deves usar TypeScript, uma linguagem que se baseia no JavaScript, mas com a sintaxe de tipos de uma linguagem de tipos estáticos.

O operador typeof

O operador typeof devolve o tipo do seu operando. O resultado é uma string que corresponde ao nome de um dos tipos de dados primitivos, exceto para "null". Também pode ser "function" ou "object".

typeof undefined;
// => "undefined"

typeof true;
// => "boolean"

typeof 42;
// => "number"

typeof 'Hello, World!';
// => "string"

typeof function () {
  return 'Hello, World';
};
// => "function"

typeof [1, 2, 3, 4];
// => "object"

typeof { city: 'Stockholm', country: 'Sweden' };
// => "object"

Por [razões históricas][typeof null is "object"].

O operador instanceof

Para verificar o tipo de um objeto, podes usar o operador instanceof. Avalia para um boolean consoante o segundo operando esteja incluído na cadeia de protótipos do primeiro operando. Para clarificar, o instanceof devolve se o primeiro operando é uma instância do segundo operando ou de uma das suas subclasses. O instanceof só funciona com objetos.

class Beverage {
  // ...
}

// The Coffee class is a child of the Beverage class.
class Coffee extends Beverage {
  // ...
}

const java = new Coffee();

java instanceof Coffee;
// => true

java instanceof Beverage;
// => true
Advanced

A classe Array tem um método chamado Array.isArray() que verifica se o seu argumento é um array.

Enquanto o instanceof Array não funciona com um array criado num realm diferente, como um iframe numa página web, o Array.isArray() funciona.

Isto acontece porque a classe Array tem um construtor diferente em cada realm, e cada iframe tem o seu próprio realm, o que significa que a função na cadeia de protótipos será diferente, fazendo com que o instanceof Array falhe. O Array.isArray() consegue ignorar isto e deve ser sempre usado quando possível.

Também consegue resistir a falsos positivos em que um objeto não é realmente um Array e tem apenas Array na sua cadeia de protótipos.

({ __proto__: Array.prototype }) instanceof Array
// => true

Array.isArray({ __proto__: Array.prototype })
// => false

O operador in

O operador in devolve se o primeiro operando é uma propriedade do segundo operando. Não verifica se a propriedade tem um valor definido. Uma propriedade com o valor undefined continua a ser detetada pelo in.

class Coffee {
  constructor() {
    this.temperature = 'hot';
    this.isDarkMatter = undefined;
  }

  coolDown() {
    this.temperature = 'warm';
  }
}

const espresso = new Coffee();

'temperature' in espresso;
// => true

'color' in espresso;
// => false

'isDarkMatter' in espresso;
// => true
Note

O in devolve true para propriedades e métodos herdados.

"coolDown" in espresso
// => true

"constructor" in espresso
// => true

Para evitar isto, usa antes o Object.hasOwn()

A função Object.hasOwn()

O método Object.hasOwn() devolve se o objeto especificado possui a propriedade indicada (não é herdada nem é um método).

class Coffee {
  constructor() {
    this.temperature = 'hot';
  }

  coolDown() {
    this.temperature = 'warm';
  }
}
const cappuccino = new Coffee();

Object.hasOwn(cappucino, 'temperature');
// => true

Object.hasOwn(cappucino, 'constructor');
// => false

Object.hasOwn(cappucino, 'coolDown');
// => false

Instruções

Instruções

Foste contratado por um centro de reciclagem. Devido à falta de espaço, todos os produtos são colocados no mesmo tapete transportador, mas isso fez com que materiais diferentes se misturassem e ficassem inutilizáveis. Para resolver isto, foi-te pedido que criasses funções para identificar o tipo de um produto.

1. Verifica se um valor é um boolean

Implementa a função isBoolean, que verifica se um valor é um boolean.

isBoolean(true);
// => true

isBoolean(null);
// => false

2. Verifica se um valor é um número.

Implementa a função isNumber, que verifica se um valor é um number ou bigint finito, ou seja, que não é NaN nem Infinity.

Às vezes, o dispositivo de leitura de IDs avaria e lê um valor não numérico como NaN (Not a Number) ou Infinity. A tua função também deve conseguir lidar com isto corretamente.

isNumber(42);
// => true

isNumber('Hello, World!');
// => false

isNumber(42n);
// => true

isNumber(NaN);
// => false

3. Verifica se um valor é um objeto

Implementa a função isObject, que deve verificar se o valor é um objeto. No tapete, null não é nada e não é considerado um objeto.

isObject({ greeting: 'Hello' });
// => true

isObject(25n);
// => false

4. Verifica se uma string é numérica

Implementa a função isNumericString, que deve verificar se o valor é uma string composta apenas por algarismos, ou por um sinal de menos seguido de algarismos, que indica um número negativo. Só devem ser considerados números inteiros; os decimais não são considerados numéricos nesta verificação do robô de reciclagem.

isNumericString(42);
// => false

isNumericString('42');
// => true

isNumericString('Hi!');
// => false

5. Verifica se um objeto é eletrónico

Implementa a função isElectronic, que verifica se um objeto é uma instância da classe ElectronicDevice fornecida ou de uma das suas subclasses.

class Duck {
  //...
}

class WashingMachine extends ElectronicDevice {
  //...
}

isElectronic(new Duck());
// => false

isElectronic(new WashingMachine());
// => true

6. Verifica se um valor é um array não vazio

Implementa a função isNonEmptyArray, que verifica se um valor é um array não vazio.

isNonEmptyArray([1, 2, 3]);
// => true

isNonEmptyArray([]);
// => false

7. Verifica se um valor é um array vazio

Implementa a função isEmptyArray, que verifica se um valor é um array vazio.

isEmptyArray([1, 2, 3]);
// => false

isEmptyArray([]);
// => true

8. Verifica se um objeto tem uma propriedade ou método type

Implementa a função hasType, que verifica se um objeto tem uma propriedade ou um método type.

class Keyboard(){
  type(){
    // ...
  }
}
hasType({ type:"car", color:"red" })
// => true

hasType({ color:"green" })
// => false

hasType(new Keyboard())
// => true

9. Lança um erro se um objeto não tiver uma propriedade ou método id

Implementa a função assertHasId, que lança um Error se um objeto não tiver a propriedade id.

Se um objeto tiver a propriedade id, a função não deve devolver nada.

assertHasId({ id: 42, color: 'red' });
// => undefined

assertHasId({ color: 'green' });
// Error: "Object is missing the 'id' property"

10. Verifica se um objeto tem uma propriedade id

Implementa a função hasIdProperty, que verifica se um objeto tem uma propriedade id.

class SimpleData {
  constructor() {
    this.number = '42';
    this.id = 'BC269327FE1D9B95';
  }
}

class StealingData extends SimpleData {}

class MethodData {
  constructor() {
    this.number = '42';
    this._id = 'BC269327FE1D9B95';
  }

  get id() {
    return this._id;
  }
}

hasIdProperty(new SimpleData());
// => true

hasIdProperty(new MethodData());
// => false

hasIdProperty(new StealingData());
// => false

11. Verifica se um objeto tem uma propriedade type definida

Implementa a função hasDefinedType, que verifica se um objeto tem uma propriedade type que não é undefined.

hasDefinedType({ type: undefined, color: 'red' });
// => false

hasDefinedType({ type: 'car', color: 'green' });
// => true
Editar via GitHub A ligação abre numa nova janela ou separador
JavaScript Exercism

Estás pronto para começar Robot de reciclagem?

Inscreve-te no Exercism para aprenderes e dominares JavaScript com 37 conceitos159 exercícios, e mentoria humana real, tudo grátis.