1. Trang chủ
  2. » Công Nghệ Thông Tin

Practical prototype and scipt.aculo.us part 9 ppsx

6 259 0
Tài liệu đã được kiểm tra trùng lặp

Đang tải... (xem toàn văn)

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 6
Dung lượng 86,71 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

For trickier collections, though, you’ll need to pass in a function to identify exactly what you want the maximum or minimum of: var words = ["flowers", "the", "hate", "moribund", "sesqu

Trang 1

Using Enumerable#select

What if we need to find several needles in a haystack?

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10].select(isEven);

//-> [2, 4, 6, 8, 10]

Just like detect,selecttests each item against the given function But it doesn’t stop

after the first match—it will return all items in the collection that match the criteria

["foo", 1, "bar", "baz", 2, null].select( function(item) {

return typeof item === "string";

});

//-> ["foo", "bar", "baz"]

Unlike detect, which is guaranteed to return only one item, selectwill always return

an array If there are no matches, it will return an empty array

Using Enumerable#reject

Nearly identical to select,rejectwill return all the items that fail a particular test.

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10].reject(isEven);

//-> [1, 3, 5, 7, 9]

Using Enumerable#partition

When you need to separate a collection into two groups, use Enumerable#partition It returns a two-item array: the first an array of all items that passed the test, and the sec-ond an array of all items that failed the test

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10].partition(isEven);

//-> [ [2, 4, 6, 8, 10], [1, 3, 5, 7, 9] ]

Sorting Collections: min, max, and sortBy

The next three Enumerablemethods—min,max, and sortBy—address common situations of arranging collections by value

Trang 2

Using Enumerable#min and #max

Much like Math.minand Math.max, which identify the smallest and largest values of all the

arguments passed to them, Enumerable#minand #maxwill find the smallest and largest

val-ues in an existing group:

Math.min(1, 4, 9, 16, 25); //-> 1

Math.max(1, 4, 9, 16, 25); //-> 25

var squares = [1, 4, 9, 16, 25];

squares.min(); //-> 1

squares.max(); //-> 25

In this example, it’s easy to figure out what the minimum and maximum values

are—numbers are directly comparable For trickier collections, though, you’ll need to

pass in a function to identify exactly what you want the maximum or minimum of:

var words = ["flowers", "the", "hate", "moribund", "sesquicentennial"];

words.max( function(word) { return word.length; } ); //-> 16

words.min( function(word) { return word.length; } ); //-> 3

Comparing on string length, we get 3and 16as the min and max, respectively—the

lengths of the shortest and longest words in the array

Using Enumerable#sortBy

JavaScript has a built-in sorting method: Array#sort Why do we need another?

Let’s illustrate If we try to use Array#sorton an example set of numbers, we’ll be

in for a surprise:

[2, 5, 4, 8, 9, 1, 3, 10, 7, 6].sort();

//-> [1, 10, 2, 3, 4, 5, 6, 7, 8, 9]

As it happens, sortcalled with no arguments will coerce the array items into strings

before it compares them (10is greater than 2, but "10"is less than "2".) If we want to

compare the numbers directly, we must pass a function argument into sort:

[2, 5, 4, 8, 9, 1, 3, 10, 7, 6].sort(function(a, b) {

return a – b;

});

//-> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

Trang 3

The passed function tells sorthow to compare any two items in the array In the pre-ceding example, if ais greater than b, then the return value will be positive, indicating that ashould followb If bis greater than a, then the return value will be negative, and a

will precedeb (If the return value is 0, then the two are equal, of course.)

This is nuts—or, at the very least, surprising We need a better sort function

Enumerable#sortByworks a little differently It, too, takes a function argument, but the function is used only to translate a given item to a comparison value:

var words = ["aqueous", "strength", "hated", "sesquicentennial", "area"];

// sort by word length

words.sortBy( function(word) { return word.length; } );

//-> ["area", "hated", "aqueous", "strength", "sesquicentennial"]

// sort by number of vowels in the word

words.sortBy( function(word) { return word.match(/[aeiou]/g).length; } )

//-> ["strength", "hated", "area", "aqueous", "sesquicentennial"]

As you can see, the comparison function takes one argument, rather than two Most developers will find this far more intuitive

Advanced Enumeration: map, inject, invoke,

and pluck

The next four Enumerablemethods carry more cryptic names, but are every bit as useful

as the methods described previously

Using Enumerable#map and Enumerable#inject

The mapmethod performs parallel transformation It applies a function to every item in

a collection, pushes each result into an array, and then returns that array

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map( function(num) { return num * num; } );

//-> [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

The injectmethod returns an accumulated collection Think of it as a hat being passed around to each of the items—each item throws a different quantity into the hat

Trang 4

var words = ["aqueous", "strength", "hated", "sesquicentennial", "area"];

var totalLength = words.inject(0, function(memo, string) {

return memo + string.length;

});

// -> 40

Since we need to keep track of memo—the variable that stores our running total—the

arguments for injectare slightly different The first argument of injectis our starting

value—0, in this case, since we’re dealing with a numeric property The second argument

is the function we’re using against the collection’s items

This inner function itself takes two arguments: our running total (memo) and the item

we’re working with (string) The function’s return value will be used as the memo for the

next item in the collection

This can be a bit confusing, so let’s add a logging statement to the inner function to

illustrate what’s going on:

var totalLength = words.inject(0, function(memo, string) {

console.log('received ' + memo + '; added ' + string.length);

console.log('returning ' + (memo + string.length));

return memo + string.length;

});

//-> received 0; added 7

//-> returning 7

//-> received 7; added 8

//-> returning 15

//-> received 15; added 5

//-> returning 20

//-> received 20; added 16

//-> returning 36

//-> received 36; added 4

//-> returning 40

//-> 40

Now that you can see each step in the enumeration, the behavior of injectshould be

easier to follow

Trang 5

Using Enumerable#pluck and Enumerable#invoke

These two Enumerablemethods are somewhat special They take a string as their first argument instead of a function

The pluckmethod collects individual properties on each of the objects on the collection:

var words = ["aqueous", "strength", "hated", "sesquicentennial", "area"];

words.pluck('length');

//-> [7, 8, 5, 16, 4]

Note that this example code is equivalent to

words.map( function(word) { return word.length; } );

but is shorter and more meaningful

The invokemethod is similar: it calls the specified instance method on each item Let’s illustrate by using one of Prototype’s string methods:

" aqueous ".strip(); //-> "aqueous"

var paddedWords = [" aqueous ", "strength ", " hated ",

"sesquicencennial", " area "];

words.invoke('strip');

//-> ["aqueous", "strength", "hated", "sesquicentennial", "area"]

This code is equivalent to

words.map( function(word) { return word.strip(); } );

but invokecan also pass arguments along to the instance method Simply add the

required number of arguments after the first:

"swim/swam".split('/'); //-> ["swim", "swam"]

"swim/swam".replace('/', '|'); //-> "swim|swam"

var wordPairs = ["swim/swam", "win/lose", "glossy/matte"];

wordPairs.invoke('split', '/');

//-> [ ["swim", "swam"], ["win", "lose"], ["glossy", "matte"] ]

wordPairs.invoke('replace', '/', '|');

//-> ["swim|swam", "win|lose", "glossy|matte"]

The map,inject,pluck, and invokemethods greatly simplify four very common code patterns Become familiar with them and you’ll start to notice uses for them all over the code you write

Trang 6

Other Collections That Use Enumerable

Two other Prototype classes that make use of Enumerableare Hashand ObjectRange

Together they serve as great examples of how to use Enumerablewith other types of

collections

Hash

There is no built-in facility in JavaScript for setting key/value pairs—the construct that’s

known as a hash (in Ruby), a dictionary (in Python), or an associative array (in PHP).

There is, of course, an ordinary object, and this suffices for most cases

var airportCodes = {

AUS: "Austin-Bergstrom Int'l",

HOU: "Houston/Hobby",

IAH: "Houston/Intercontinental",

DAL: "Dallas/Love Field",

DFW: "Dallas/Fort Worth"

};

for (var key in airportCodes) {

console.log(key + " is the airport code for " + airportCodes[key] + '.');

}

>>> AUS is the airport code for Austin-Bergstrom Int'l

>>> HOU is the airport code for Houston/Hobby

>>> IAH is the airport code for Houston/Intercontinental

>>> DAL is the airport code for Dallas/Love Field

>>> DFW is the airport code for Dallas/Fort Worth

We can declare an object and iterate over its properties quite easily This doesn’t get

us everything a hash would, but it comes very close

Eventually, however, we’ll run into two major problems

Objects Have No Key Safety

An object is not a blank slate when it’s declared It has native properties and methods

with names that may conflict with the names you’d want to use for your keys

Ngày đăng: 03/07/2014, 01:20