• No se han encontrado resultados

Aspectos   relacionados   con   la   ley   periódica   y   los   formatos   para   representarla

libros  de  texto  y  en  las  clases

4.2 Diseño  de  la  encuesta  y  la  plantilla  de  análisis

4.2.3 Aspectos   relacionados   con   la   ley   periódica   y   los   formatos   para   representarla

JS Generation

The JavaScript generation for non ES6 targets simply involves creating temporary variables, ust like you would have to do yourself without native language support for destructuring e.g.

Destructuring

var x =1, y =2;

[x, y] = [y, x];

console.log(x, y);// 2,1 // becomes //

var x =1, y =2;

_a = [y,x], x = _a[0], y = _a[1];

console.log(x, y);

var _a;

Summary Summary

Destructuring can make your code more readable and maintainable by reducing the line count and making the intent clear. Array destructuring can allow you to use arrays as though they were tuples.

for...of for...of

A common error experienced by beginning JavaScript developers is that for...in for an array does not iterate over the array items. Instead it iterates over thekeys of the object passed in. This is demonstrated in the below example. Here you would expect 9,2,5 but you get the indexes 0,1,2:

var someArray = [9,2,5];

for (var itemin someArray) { console.log(item);// 0,1,2 }

This is one of the reasons why for...of exists in TypeScript (and ES6). The following iterates over the array correctly logging out the members as expected:

var someArray = [9,2,5];

for (var item of someArray) { console.log(item);// 9,2,5 }

Similarly TypeScript has no trouble going through a string character by character using

for...of:

var hello ="is it me you're looking for?"; for (var char of hello) {

console.log(char);// is it me you're looking for?

}

JS Generation JS Generation

For pre ES6 targets TypeScript will generate the standard for (var i = 0; i < list.length;

i++) kind of loop. For example here's what gets generated for our previous example:

for...of

var someArray = [9,2,5];

for (var item of someArray) { console.log(item);

}

// becomes //

for (var _i =0; _i < someArray.length; _i++) { var item = someArray[_i];

console.log(item);

}

You can see that using for...of makesintent clearer and also decreases the amount of code you have to write (and variable names you need to come up with).

Limitations Limitations

If you are not targeting ES6 or above, the generated code assumes the property length

exists on the object and that the object can be indexed via numbers e.g obj[2]. So it is only supported on string and array for these legacy JS engines.

If TypeScript can see that you are not using an array or a string it will give you a clear error

"is not an array type or a string type" ;

let articleParagraphs =document.querySelectorAll("article > p");

// Error: Nodelist is not an array type or a string type for (let paragraph of articleParagraphs) {

paragraph.classList.add("read");

}

Use for...of only for stuff thatyou know to be an array or a string. Note that this limitation might be removed in a future version of TypeScript.

Summary Summary

You would be surprised at how many times you will be iterating over the elements of an array. The next time you find yourself doing that, give for...of a go. You might just make the next person who reviews your code happy.

Iterators Iterators

Iterator itself is not a TypeScript or ES6 feature, Iterator is a Behavioral Design Pattern common for Object oriented programming languages. It is, generally, an object which implements the following interface:

interface Iterator<T> {

next(value?:any): IteratorResult<T>;

return?(value?:any): IteratorResult<T>;

throw?(e?:any): IteratorResult<T>;

}

This interface allows to retrieve a value from some collection or sequence which belongs to the object.

Imagine that there's an object of some frame, which includes the list of components of which this frame consists. With Iterator interface it is possible to retrieve components from this frame object like below:

Iterators

'use strict';

class Component {

constructor (public name: string) {}

}

class Frame implements Iterator<Component> { private pointer =0;

constructor(public name: string, public components: Component[]) {}

public next(): IteratorResult<Component> { if (this.pointer <this.components.length) {

return {

let frame = new Frame("Door", [new Component("top"), new Component("bottom"), new Comp onent("left"), new Component("right")

let iteratorResult1 = frame.next();//{ done: false, value: Component { name: 'top' } }

let iteratorResult2 = frame.next();//{ done: false, value: Component { name: 'bottom' } }

let iteratorResult3 = frame.next();//{ done: false, value: Component { name: 'left' } }

let iteratorResult4 = frame.next();//{ done: false, value: Component { name: 'right' } }

let iteratorResult5 = frame.next();//{ done: true }

//It is possible to access the value of iterator result via the value property:

let component = iteratorResult1.value;//Component { name: 'top' }

Again. Iterator itself is not a TypeScript feature, this code could work without implementing Iterator and IteratorResult interfaces explicitly. However it is very helpful to use these common ES6interfaces for code consistency.

Ok, Nice, but could be more helpful. ES6 defines theiterable protocol which includes [Symbol.iterator] symbol if Iterable interface implemented:

//...

class Frame implements Iterable<Component> {

constructor(public name: string, public components: Component[]) {}

[Symbol.iterator]() {

let pointer =0;

let components =this.components;

return {

next(): IteratorResult<Component> { if (pointer < components.length) {

return { done: false,

value: components[pointer++]

} } else {

return { done: true }

} }

}

}

}

let frame = new Frame("Door", [new Component("top"), new Component("bottom"), new Comp onent("left"), new Component("right")

for (let cmp of frame) { console.log(cmp);

}

Unfortunately frame.next() won't work with this pattern and it also looks a bit clunky.

IterableIterator interface to the rescue!

Iterators

//...

class Frame implements IterableIterator<Component> { private pointer =0;

constructor(public name: string, public components: Component[]) {}

public next(): IteratorResult<Component> { if (this.pointer <this.components.length) {

return { done:false,

value:this.components[this.pointer++]

} }else {

return { done:true }

} }

[Symbol.iterator](): IterableIterator<Component> { return this;

}

} //...

Both frame.next() and for cycle now work fine with IterableIterator interface.

Iterator does not have to iterate a finite value. The typical example is a Fibonacci sequence:

class Fib implements IterableIterator<number> {

protected fn1 =0;

protected fn2 =1;

constructor(protected maxValue?: number) {}

public next(): IteratorResult<number> { var current =this.fn1;

this.fn1 = this.fn2;

this.fn2 = current +this.fn1;

if (this.maxValue && current <=this.maxValue) { return {

[Symbol.iterator](): IterableIterator<number> { return this;

}

}

let fib = new Fib();

fib.next()//{ done: false, value: 0 } fib.next()//{ done: false, value: 1 } fib.next()//{ done: false, value: 1 } fib.next()//{ done: false, value: 2 } fib.next()//{ done: false, value: 3 } fib.next()//{ done: false, value: 5 }

let fibMax50 =new Fib(50);

console.log(Array.from(fibMax50));// [ 0, 1, 1, 2, 3, 5, 8, 13, 21, 34 ]

let fibMax21 =new Fib(21);

for(let num of fibMax21) {

console.log(num);//Prints fibonacci sequence 0 to 21 }