JS 30 是由加拿大的全端工程师 Wes Bos 免费提供的 JavaScript 简单应用课程,课程主打 No Frameworks
、No Compilers
、No Libraries
、No Boilerplate
在30天的30部教学影片里,建立30个JavaScript的有趣小东西。
另外,Wes Bos 也很无私地在 Github 上公开了所有 JS 30 课程的程序码,有兴趣的话可以去 fork 或下载。
练习一些 Array 常用的方法,包括 filter()、sort()、map()、reduce()。
前七个练习题要使用的资料如下:
/*JS*/
// Get your shorts on - this is an array workout!
// ## Array Cardio Day 1
// Some data we can work with
const inventors = [
{ first: 'Albert', last: 'Einstein', year: 1879, passed: 1955 },
{ first: 'Isaac', last: 'Newton', year: 1643, passed: 1727 },
{ first: 'Galileo', last: 'Galilei', year: 1564, passed: 1642 },
{ first: 'Marie', last: 'Curie', year: 1867, passed: 1934 },
{ first: 'Johannes', last: 'Kepler', year: 1571, passed: 1630 },
{ first: 'Nicolaus', last: 'Copernicus', year: 1473, passed: 1543 },
{ first: 'Max', last: 'Planck', year: 1858, passed: 1947 },
{ first: 'Katherine', last: 'Blodgett', year: 1898, passed: 1979 },
{ first: 'Ada', last: 'Lovelace', year: 1815, passed: 1852 },
{ first: 'Sarah E.', last: 'Goode', year: 1855, passed: 1905 },
{ first: 'Lise', last: 'Meitner', year: 1878, passed: 1968 },
{ first: 'Hanna', last: 'Hammarström', year: 1829, passed: 1909 }
];
const people = [
'Bernhard, Sandra', 'Bethea, Erin', 'Becker, Carl', 'Bentsen, Lloyd', 'Beckett, Samuel', 'Blake, William', 'Berger, Ric', 'Beddoes, Mick', 'Beethoven, Ludwig',
'Belloc, Hilaire', 'Begin, Menachem', 'Bellow, Saul', 'Benchley, Robert', 'Blair, Robert', 'Benenson, Peter', 'Benjamin, Walter', 'Berlin, Irving',
'Benn, Tony', 'Benson, Leana', 'Bent, Silas', 'Berle, Milton', 'Berry, Halle', 'Biko, Steve', 'Beck, Glenn', 'Bergman, Ingmar', 'Black, Elk', 'Berio, Luciano',
'Berne, Eric', 'Berra, Yogi', 'Berry, Wendell', 'Bevan, Aneurin', 'Ben-Gurion, David', 'Bevel, Ken', 'Biden, Joseph', 'Bennington, Chester', 'Bierce, Ambrose',
'Billings, Josh', 'Birrell, Augustine', 'Blair, Tony', 'Beecher, Henry', 'Biondo, Frank'
];
Array.prototype.filter()
filter()
方法会透过指定的函式运算,决定保留哪些资料并形成一个新的阵列。
在 filter()
里 return true 代表要保留该笔资料,除此之外的资料都会被舍弃,我们没必要再写 else 去 return false。
以下我们透过 filter()
过滤"出生於16世纪的发明家"。
/*JS*/
const fifteen = inventors.filter(function(inventor){
if(inventor.year >= 1500 && inventor.year < 1600){
return true; //keep it in the new array
}
})/*除了有回传true之外的东西都会被丢掉,不必再用else return false*/
更简洁的写法:
console.table()
,可以将 Array 以表格的形式呈现出来。
/*JS*/
const fifteen = inventors.filter(inventor => (inventor.year >= 1500 && inventor.year < 1600));
console.table(fifteen);
Array.prototype.map()
map()
方法会建立一个和原阵列长度相同的阵列,其内容为原阵列的每一个元素经由指定的函式运算後所回传的结果之集合。
以下我们使用 map()
方法,将发明家的 first name 和 last name 结合在一起,形成一个新的阵列。
/*JS*/
const fullNames = inventors.map(inventor => `${inventor.first} ${inventor.last}`); /*Template literals*/
console.table(fullNames);
Array.prototype.sort()
sort()
方法会对一个阵列中的所有元素进行排序,并回传此阵列,预设是以字串的 Unicode 编码进行排序。
我们也可以指定一个compareFunction
,用自订的排序规则为阵列进行排序。
compareFunction(a, b)
,回传值小於0时,a 会被排在 b 的前面,反之若回传值大於0时,a 会被排在 b 的後面。
以下我们使用 sort()
,将较早出生的发明家排在前面的位置。
const ordered = inventors.sort(function(a,b){
if(a.year > b.year){
return 1; /*a 往後排*/
}else{
return -1; /*a 往前排*/
}
})
更简洁的写法:
const ordered = inventors.sort((a,b) => a.year > b.year ? 1 : -1);
console.table(ordered);
Array.prototype.reduce()
reduce()
方法将一个累加器(accumulator)及阵列中每项元素传入函式中进行运算,将阵列化为单一的值。
其中一种用法如下:
Array.reduce((accumulator,currentValue) => {
return accumulator + currentValue;
},initialValue); /*initialValue 是 accumulator 的初始值*/
另一种用法如下:
const totalYears = inventors.reduce((total,inventor)=>{
return total + (inventor.passed - inventor.year);
},0);
console.log(totalYears);
以下我们将这些发明家依照寿命的长短由大到小进行排序。
透过 passed - year
,我们可以很简单的算出每一位发明家的寿命。
const oldest = inventors.sort(function(a,b){
const lastGuy = a.passed - a.year;
const nextGuy = b.passed - b.year;
return lastGuy > nextGuy ? -1 : 1;
});
console.table(oldest)
这题我们需要自行到 https://en.wikipedia.org/wiki/Category:Boulevards_in_Paris 右键检查进入 console 进行解题。
Node.textContent
可以取得节点或其後代的文字内容。
Array.prototype.includes()
includes()
方法会判断阵列是否包含特定的元素,并以此来回传 true
或 false
。
Array.from()
从类阵列(array-like,例如: NodeList)或是可迭代(iterable)物件建立一个新的 Array
实体。
首先,我们取得包覆所有巴黎大道名称的最上层 div 标签(.mw-category
)。接着,取得在其之下的所有连结(a
)。最後,使用 map()
方法以所有连结的内部文字组成新阵列并透过 filter()
过滤出包含(include)'de'的所有大道名称。
const category = document.querySelector('.mw-category');
const links = Array.from(category.querySelectorAll('a'));/*NodeList*/
const de = links.map(link => link.textContent).filter(streetName => streetName.includes('de'));
console.table(de);
String.prototype.split()
split()
方法可以使用指定的分隔字元(separator)将一个String
分割成串列。
以下用,
(逗号和空格)作为分隔字元将 first name、last name 切开并放入一个阵列中,接下来就可以依照 aLast、bLast 的 Unicode 进行 last name 的排序(由小到大)。
const alpha = people.sort(function(lastOne,firstOne){
const [aLast,aFirst] = lastOne.split(', ');
const [bLast,bFirst] = firstOne.split(', ');
return aLast > bLast ? 1 : -1;
});
另一种写法:
const alpha = people.sort((lastOne,firstOne) => {
const [aLast,aFirst] = lastOne.split(', ');
const [bLast,bFirst] = firstOne.split(', ');
return aLast > bLast ? 1 : -1;
});
资料内容:
const data = ['car', 'car', 'truck', 'truck', 'bike', 'walk', 'car', 'van', 'bike', 'walk', 'car', 'van', 'car', 'truck' ];
一开始赋予累加器(obj)的初始值(initial value)为空物件({}),因为最初所有的 item 都不存在於 obj 中,所以透过 if 判断当 obj[item] 不存在时,就建立 obj[item] 并赋予初始值0。其後就可正常将 item 持续累加至正确的交通工具分类中(obj[item]++)。
const transportation = data.reduce(function(obj,item){
if(!obj[item]){
obj[item] = 0;
}
obj[item]++;
return obj;
},{})
console.table(transportation);
<<: Day 03:「开始乘风飞行!」- 样式都不见了吗?快用 Tailwind 轻松调整文字版式
>>: [Day 03] 在Windows上用IIS架Laravel网站
PIXI.Ticker 之前介绍的pixi.application创造的五个的剩最後一个 loade...
有些公司会有上机的程序考题,相信初心者会怕怕(我个人是会啦),但从简单的题目开始学习吧! 把阵列 ...
小回顾 Day01 - 缘起:怎麽了?为什麽?如何掌握过於自由的程序码? 以订单、RPG 角色的移动...
聊完有线上网,我们接着从 Wi-Fi 开始,到提供行动上网不同世代,看看这些服务是怎麽出现的,又用了...
Day 11 - Kotlin的函式(2) 昨天我们讲了list集合,以及如何取得数值,今天我们要继...