『初めてのJavaScript(第3版 )』非公式練習問題 – 浅野直樹の学習日記で作った『初めてのJavaScript(第3版 )』非公式練習問題の解答例です。自分で学習しながら作ったものなので不備があるかもしれません。
2章
練習問題
ex02-08-1のjsファイルを次のように書き加えます。
$(document).ready(function() {
'use strict';
paper.install(window);
paper.setup(document.getElementById('mainCanvas'));
let tool = new Tool();
tool.onMouseDown = function(event) {
let c = Shape.Circle(event.point.x, event.point.y, 80);
c.fillColor = 'blue';
let text = new PointText(event.point.x, event.point.y);
text.justification = 'center';
text.fillColor = 'yellow';
text.fontSize = 20;
text.content = 'hello world';
};
});
3章
練習問題1
次のようなjsファイルを作ります。
const date = new Date();
let message1 = "今日は" + date.getFullYear() + "年" + (date.getMonth()+1) + "月" + date.getDate() + "日です。\n"
date.setDate(date.getDate()+20);
let message2 = "20日後は" + date.getFullYear() + "年" + (date.getMonth()+1) + "月" + date.getDate() + "日です。\n"
console.log(message1, message2);
練習問題2
次のようなjsファイルを作ります。
const b4 = [
{ 名前: "ルビー", 硬度: 9 },
{ 名前: "ダイヤ", 硬度: 10 },
{ 名前: "トパーズ", 硬度: 8 },
];
b4[99] = { 名前: "象牙", 硬度: 2.5 };
let message = b4[b4.length - 1].名前 +"の硬度は" + b4[b4.length - 1].硬度 +"です。";
console.log(message);
4章
練習問題
次のように、challengeという変数を新たに作り、whileにとどまる条件を変えて、手持ち資金が0になれば再挑戦するようにします。
'use strict';
function rand(m, n) {
return m + Math.floor((n - m + 1)*Math.random());
}
function randFace() {
return ["crown", "anchor", "heart", "spade", "club", "diamond"]
[rand(0, 5)];
}
let funds = 50;
let round = 0;
let challenge = 1;
while(funds < 100) {
round++;
console.log(`第${round}ラウンド: `);
console.log(` 手持ち資金: ${funds}`);
let bets = { crown: 0, anchor: 0, heart: 0,
spade: 0, club: 0, diamond: 0 };
let totalBet = rand(1, funds);
if(totalBet === 7) {
totalBet = funds;
bets.heart = totalBet;
} else {
let remaining = totalBet;
do {
let bet = rand(1, remaining);
let face = randFace();
bets[face] = bets[face] + bet;
remaining = remaining - bet;
} while(remaining > 0)
}
funds = funds - totalBet;
console.log(` 賭け金: ${totalBet}(` +
Object.keys(bets).map(face => `${face}: ${bets[face]}`).join(', ') +
")");
const hand = [];
for(let roll = 0; roll < 3; roll++) {
hand.push(randFace());
}
console.log(` 出目: ${hand.join(', ')}`);
let winnings = 0;
for(let die=0; die < hand.length; die++) { let face = hand[die]; if(bets[face] > 0) winnings = winnings + bets[face];
}
funds = funds + winnings;
console.log(` 払戻金: ${winnings}`);
if (funds <= 0) {
funds = 50;
round = 0;
challenge++;
}
}
console.log(` 残金: ${funds}`);
console.log(challenge + "回目の挑戦で意気揚々と船に戻りました。");
5章
練習問題
例えば以下のようにします。
const nums = [ 3, 5, 15, 7, 5 ];
let n, i=0, j=0;
while(i<nums.length && (n = nums[i++]) % 2 ) {
console.log(`奇数を発見:${n}`);
j++;
}
if (i !== j) {
console.log(`偶数を発見:${n}`);
}
console.log(`未チェックの数字の個数:${nums.length-i}`);
6章
練習問題
例えば次のようなjsファイルを作ります。
const asano = { 名前: "浅野" };
function update(birthYear, occupation, address) {
this.誕生年 = birthYear;
this.職業 = occupation;
this.居住地 = address;
}
console.log(asano);
update.call(asano, 1982, "塾講師", "京都府");
update.apply(asano, [1982, "塾講師", "京都府"]); // この行のapplyか上の行のcallのどちらか1つでよい。
console.log(asano);
const updateAsano1982 = update.bind(asano, 1982);
updateAsano1982("プログラマー", "東京都");
console.log(asano);
7章
練習問題
オブジェクトのプロパティを書き換えた場合にはスコープから外れても値が元に戻りません(6.3を参照)。
function update(birthYear, occupation, address) {
this.誕生年 = birthYear;
this.職業 = occupation;
this.居住地 = address;
}
{ /* 外側のブロックの始まり */
let asano = { 名前: "浅野", 誕生年: 1982, 職業: "塾講師", 居住地: "京都府"};
console.log(asano);
{ /* 内側のブロックの始まり */
update.call(asano, 1982, "塾講師", "東京都");
console.log(asano);
} /* 内側のブロックの終わり */
console.log(asano);
} /* 外側のブロックの終わり */
console.log(typeof asano);
8章
練習問題1
以下のようにします。
let arr = [{ name: "Suzanne" }, { name: "Jim" },
{ name: "Trevor" }, { name: "Amanda" }];
arr.sort((a, b) => a.name > b.name); // nameでソート
arr.sort((a, b) => a.name.length > b.name.length); //文字数でソート
console.log(arr);
練習問題2
以下のようにします。
function 記号表現に変換する(カード) {
const マーク名_絵文字
= { 'ハート': '♡', 'クローバー': '♧', 'ダイア': '♢', 'スペード': '♤' };
const 数字からAJQK = { 1: 'A', 11: 'J', 12: 'Q', 13: 'K' };
for(let i=2; i<=10; i++) 数字からAJQK[i] = i;
return マーク名_絵文字[カード.マーク]+数字からAJQK[カード.数字];
}
const カードの束 = [];
for(let マーク of ['ハート', 'クローバー', 'ダイア', 'スペード']) // 全カードを生成
for(let 数字=1; 数字<=13; 数字++) カードの束.push({ マーク, 数字});
let 選択されたカード_記号表現
= カードの束.filter(カード => カード.マーク === 'スペード' && (カード.数字 >= 10 || カード.数字 === 1)).map(記号表現に変換する);
console.log(選択されたカード_記号表現);
練習問題3
次のようにします。
const words = ["Beachball", "Rodeo", "Angel",
"Aardvark", "Xylophone", "November", "Chocolate",
"Papaya", "Uniform", "Joker", "Clover", "Bali"];
const longWords = words.filter(word => word.length > 6);
let result = longWords.join(' ');
console.log(result);
const 単語リスト
= ["ビーチボール", "ルービックキューブ", "ブタペスト", "トロッコ",
"コンゴ", "ゴースト", "トーラス", "スマート", "トンガ",
"ガラパゴス", "ストリート", "トーマス", "ストレッチ",
"チベット", "トキ", "キツツキ", "キリン"];
const 長い単語 = 単語リスト.filter(単語 => 単語.length >= 5);
let 結果 = 長い単語.join(' ');
console.log(結果);
9章
練習問題
例えば以下のようにします。
class Vehicle {
constructor() {
this.passengers = [];
console.log("Vehicleが生成された");
}
addPassenger(p) {
this.passengers.push(p);
console.log(`${p}が${this.constructor.name}に乗り込み、今${this.passengers.length}人乗っています。`);
}
}
class Car extends Vehicle {
constructor() {
super();
this.capacity = 5;
console.log("Carが生成された");
}
addPassenger(p) {
Vehicle.prototype.addPassenger.call(this, p);
if (this.capacity - this.passengers.length < 0) {
console.log('定員オーバーです');
return;
}
console.log(`あと${this.capacity - this.passengers.length}人です`);
}
}
const v = new Vehicle();
v.addPassenger("太郎");
v.addPassenger("花子");
const c = new Car();
c.addPassenger("景子");
c.addPassenger("ミドリ");
c.addPassenger("一郎");
c.addPassenger("二郎");
c.addPassenger("三郎");
c.addPassenger("四郎");
c.addPassenger("五郎");
10章
練習問題
次のようにします。
const u1 = { name: '和洋' };
const u2 = { name: '花子' };
const u3 = { name: '涼子' };
const u4 = { name: '哲人' };
const userRoles = new Map();
const rolesU1 = new Set();
rolesU1.add("ユーザー");
userRoles.set(u1, rolesU1);
const rolesU2 = new Set();
rolesU2.add("管理者");
userRoles.set(u2, rolesU2);
const rolesU3 = new Set();
rolesU3.add("ユーザー");
rolesU3.add("管理者");
userRoles.set(u3, rolesU3);
const rolesU4 = new Set();
userRoles.set(u4, rolesU4);
for (let [u, r] of userRoles.entries()) {
let allRoles = [];
for (let value of r.values()) {
allRoles.push(value);
}
console.log(`${u.name}: ${allRoles}`);
}
11章
練習問題
次のようにします。
const email = "jane@doe.com;
function validateEmail(email) {
return email.match(/@/) ?
email :
new Error(`無効なメールアドレスです:${email}`);
}
try {
const validatedEmail = validateEmail(email);
console.log(validatedEmail);
if(validatedEmail instanceof Error) {
console.error(validatedEmail.message);
} else {
console.log(`正しい形式のアドレス:${validatedEmail}`);
}
} catch(err) {
console.error(`エラー:${err.message}`);
} finally {
console.log("この行はいつも実行される");
}
12章
練習問題
次のようにします。
function* interrogate() {
const name = yield "お名前は?";
if (!name) {
return "お名前がないので終了します。";
}
const color = yield "お好きな色は何ですか?";
return `${name}さんの好きな色は${color}だそうですよ。`;
}
const it = interrogate();
console.log(it.next());
console.log(it.next(''));
console.log(it.next('緑'));
console.log(it.next());
13章
練習問題1
これは色がとばされます。
setInterval(function() {
document.querySelector('.rainbow')
.style['background-color'] = getNextRainbowColor();
}, 500);
setInterval(function() {
getNextRainbowColor();
}, 800);
const getNextRainbowColor = (function() {
const colors = ['red', 'orange', 'yellow', 'green', 'blue', 'indigo', 'violet'];
let colorIndex = -1;
return function() {
if(++colorIndex >= colors.length) colorIndex = 0;
return colors[colorIndex];
};
})();
これは色がとばされません。
const rainbowIterator = getRainbowIterator();
setInterval(function() {
document.querySelector('.rainbow')
.style['background-color'] = rainbowIterator.next().value;
}, 500);
setInterval(function() {
getRainbowIterator();
}, 800);
function getRainbowIterator() {
const colors = ['red', 'orange', 'yellow', 'green', 'blue', 'indigo', 'violet'];
let colorIndex = -1;
return {
next() {
if(++colorIndex >= colors.length) colorIndex = 0;
console.log("in iterator: "+colors[colorIndex])
return { value: colors[colorIndex], done: false };
}
};
}
練習問題2
例えば次のようにします。
function fibonacci(m, n) {
console.log(n);
if (n > 10000) {
return;
}
o = n;
p = m + n;
fibonacci(o, p);
}
fibonacci(1, 1);
13章
練習問題
例えば次のようにします。
function countdown(seconds) {
const timeoutIds = [];
for(let i=seconds; i>=0; i--) {
timeoutIds.push(setTimeout(function() {
if(i===13) {
timeoutIds.forEach(clearTimeout);
const err = new Error(`${i}という数は不吉過ぎます`);
console.error(err);
return;
}
if(i>0) console.log(i + '...');
else {
console.log("GO!");
launch(10000);
}
}, (seconds-i)*1000))
}
}
function launch(period) {
const timeoutId = setTimeout(function() {
const err = new Error('時間切れです。');
console.error(err);
}, 4000);
if(Math.random() < 0.5)
return;
console.log("発射!");
setTimeout(function() {
console.log("周回軌道に乗った!");
clearTimeout(timeoutId);
}, 2*1000);
}
countdown(3);
15章
練習問題
moment.jsを使って次のようにします。
const d = moment.tz([2018, 1, 21, 15, 00], 'Europe/London');
console.log(d.format("YYYY年M月D日HH:mm") + "にロンドンを出発しました。")
d.add(13, 'hours');
d.tz('Asia/Tokyo');
console.log(d.format("YYYY年M月D日HH:mm") + "に東京に到着しました。")
16章
練習問題
次のようにします。配列は0からスタートすることに注意してください。htmlファイルで<script src="https://cdnjs.cloudflare.com/ajax/libs/numeral.js/2.0.6/numeral.min.js"></script>
としてNumeral.jsを読み込んでください。
const revenues = [{"北海道":2434886692}, {"青森県":694217643}, {"岩手県":1129941686}, {"宮城県":1383490525}, {"秋田県":605089076}, {"山形県":580851300}, {"福島県":2096640231}, {"茨城県":1087054495}, {"栃木県":763338596}, {"群馬県":736096433}, {"埼玉県":1722075796}, {"千葉県":1659525591}, {"東京都":7122485322}, {"神奈川県":2032743502}, {"新潟県":1055947285}, {"富山県":508721490}, {"石川県":567888708}, {"福井県":450596001}, {"山梨県":465327187}, {"長野県":819099327}, {"岐阜県":773302893}, {"静岡県":1152621919}, {"愛知県":2263393575}, {"三重県":700154974}, {"滋賀県":509495460}, {"京都府":899170238}, {"大阪府":2776964207}, {"兵庫県":1962884485}, {"奈良県":493578569}, {"和歌山県":541231559}, {"鳥取県":358191520}, {"島根県":505631628}, {"岡山県":685819845}, {"広島県":923347710}, {"山口県":640430917}, {"徳島県":478647031}, {"香川県":448601297}, {"愛媛県":622066841}, {"高知県":453349565}, {"福岡県":1693270092}, {"佐賀県":435430115}, {"長崎県":695693042}, {"熊本県":1018938275}, {"大分県":572602476}, {"宮崎県":565437227}, {"鹿児島県":789070662}, {"沖縄県":747747470}]
let rand = 1 + Math.floor(47*Math.random());
for (key in revenues[rand-1]) {
console.log(`2016年の${key}の歳入は${numeral(revenues[rand-1][key]).format('0,0')}円です。`);
}
17章
練習問題
次のようにします。
const text = "Visit oreilly.com today!";
const link = text.replace(/([a-z0-9]+(?:\.com|\.org|\.edu))/ig, '<a href="$1">$1</a>');
console.log(link);
18章
練習問題
例えば次のようにします。
document.querySelector('button').addEventListener('click', ChangeAndAddText);
function ChangeAndAddText(evt) {
evt.preventDefault();
const text1 = document.getElementById("text1").value;
const originalp = document.querySelector('p');
originalp.textContent = text1;
originalp.classList.add('red');
const text2 = document.getElementById("text2").value;
const p = document.createElement('p');
p.textContent = text2;
document.querySelector('body').appendChild(p);
}
19章
練習問題
例えば次のようにします。
$(function() {
$('button').click(ChangeAndAddText);
function ChangeAndAddText(evt) {
evt.preventDefault();
const text1 = $('#text1').val();
$('p').eq(0).text(text1).addClass('red');
const text2 = $('#text2').val();
const p = $('
‘); p.text(text2); $(‘body’).append(p); } })
20章
練習問題
例えば次のようにします。
const fs = require('fs');
const path = require('path');
fs.readFile(path.join(__dirname, 'hello.txt'),
{ encoding: 'utf8' }, function(err, data) {
if(err) return console.error('エラー:ファイルから読み込めません。');
message = data.replace(/Node/g, 'Node.js');
fs.writeFile(path.join(__dirname, 'hello2.txt'),
message + '文字列を置換しました。', function(err) {
if(err) return console.log('エラー:ファイルに書き込めません。');
});
});
21章
練習問題
例えば次のようにします。
const COLOR = Symbol();
class Triangle {
constructor(a, b, c) {
this.a = a;
this.b = b;
this.c = c;
}
get perimeter() {
return this.a + this.b + this.c;
}
get area() {
const a = this.a;
const b = this.b;
const c = this.c;
return Math.sqrt((a+b+c)*(-a+b+c)*(a-b+c)*(a+b-c))/4;
}
set color(value) {
this[COLOR] = value;
}
get color() {
return this[COLOR];
}
}
const t = new Triangle(3, 4, 5);
t.color = 'red';
console.log(`外周の長さ: ${t.perimeter}`);
console.log(`面積: ${t.area}`);
console.log(`色: ${t.color}`);