※この記事は8/30/2019に書かれたブログになります。
これは「コードクリサリスへの入学方法」の続きにあたる記事になります。コードクリサリスの選考プロセスに興味のある方はぜひそちらも読んでみてくださいね。
この記事は、コードクリサリス・イマーシブコースに入学するための、第2選考についての記事です。第2選考では、みなさんは私やほかの講師とペアを組み、JavaScriptを使った一連のクイズや問題を解いていくことになっています。
こうしたテクニカル・インタビューを実施するのには、3つの目的があります:
- 応募者が、イマーシブコースのプレコースを無事終えられるだけの技術力を備えているかを判断するため。
- 慣れない課題に対して、応募者がどのように対応し、何を行うかを見るため。
- 応募者が、コードクリサリスの目指す教育環境に順応できるかを見極めるため。
また、このテクニカル・インタビューを行うことで、みなさんは実際の採用面接に近い状況を経験することができます。コードクリサリス側が評価し、フィードバックを返す根拠としているものは、企業が応募者に求めているのと同じものです。
その意味で、コードクリサリスでの学習は、みなさんが12週間のコースを受ける何ヶ月も前から始まっていることになります。
ここからは、応募者のみなさんがよくつまづく、10個のポイントをご紹介します。
コードクリサリスでは、直接答えを教える代わりに、問題の本質を見直して、間違いを犯し、自分で調べ抜くためのヒントと勇気を提供しています。
1. オブジェクト・リテラルにおける、ドット記法 VS. ブラケット記法
次のようなオブジェクト・リテラルを考えましょう。
const object = {
a: 1,
b: 2,
c: 3
};
(ちなみにオブジェクト・リテラルとは、上記のようなオブジェクトの使い方を指す、ちょっと洒落た言葉のことです。文字通りのオブジェクトです)
ブラケット記法では、このオブジェクトのキーを使うことで、それぞれの値にアクセスすることができます。
object[‘a’]
// 1
object[‘b’]
// 2
object[‘c’]
// 3
ドット記法でも同様ですね。
object.a
// 1
object.b
// 2
object.c
// 3
では一体、この2つの違いは何でしょうか? 以下のコードをコンソールで実行してみてください。
const object = {
a: 1,
b: 2,
c: 3
};
let key = ‘a’;
console.log(object.key);
console.log(object[key]);
console.log(object.a);
console.log(object[a]);
結果はどうなったでしょうか? そうなった理由は何でしょうか?
参考:
2. コールスタックを理解できていない
とても基本的な例を見てみましょう。
function sayHi() {
console.log('Hello');
return 'Hi';
}
let foo = sayHi();
console.log(foo);
console.log(foo);
上のコードは、Hello
とHi
を何回コンソールに表示するでしょうか?
こちらはもう少し発展的な例です。
function foo() {
console.log('foo');
bar();
}
function bar() {
console.log('bar');
}
function baz(fn) {
console.log('baz');
fn();
}
baz(foo);
ここでは何が起きているでしょうか? そしてその理由を説明できますか?
もう一つ例を見てみましょう。
function getNumber() {
return 5;
}
function invokeSomething(fn) {
return fn();
}
次のどちらの行が、問題なく動くでしょうか?
invokeSomething(getNumber()); // Choice A
invokeSomething(getNumber); // Choice B
その理由は何でしょう?
参考:
- Eloquent JavaScript Chapter 3: Call Stack
- Understanding the JavaScript Call Stack (非同期のコードについては無視しても大丈夫です。まだそれについて知っておく必要はありません)
3. リターンキーワードの動作
Return
は、関数の宣言の中身でのみ利用できる唯一のキーワードで、2つの役割を担っています。それは、関数にアウトプットを渡すことと、その関数のさらなる実行を止めることです。
もしアウトプットが渡されなかったら(つまりreturn
キーワードが使われていなかったら)、その関数はundefined
を返します。
下記の例を見てみましょう。
function noReturn() {
console.log(‘Print!’);
}
let whatsMyReturn = noReturn();
console.log(whatsMyReturn);
コンソールには何が表示されますか? その理由は?
また、すでに述べた通り、return
キーワードにはその関数が実行され続けるのを防ぐ役割もあります。つまり、もしfor
ループのなかにreturn
キーワードがあるようなコードの場合、そのループは最初のきっかけで終了することになります。
どういう意味でしょうか? 自分のコードで実際に試してみてください。
参考
- MDN return documentation
- Eloquent JavaScript Chapter 3 (
return
についての段落) - Javascript.info − Functions: Returning a Value
4. ネイティブ・メソッドに過度に頼りすぎている
もしあなたが、あらゆる状況で.forEach
や.map
を使っているとしたら、それらを使わずに問題を解く練習をすることをおすすめします。
ビルトインのコードを使う前に、それらがどうやって動くのか理解できるようになりましょう。もしもその理解が十分でないままだと、いつも半ば盲目的にコードを書く羽目になります。必ず、何を書いているか自覚的になりましょう。あなたのキャリアは、それができるかどうかで大きく変わってきます。
5. コードが動かないのに、完璧を目指そうとする
エレガントな解き方ができなくても、不満に思う必要はありません。まずは、ちゃんと動くコードを書きましょう。そのあとに見返して、改善していければ問題ありません。
動いていても汚いコードは、一度壊れて、まだ壊れたままのコードより断然マシです!
6. 配列とオブジェクトの違いを理解できていない
{}
と[]
は一見似ていますが、同じものではありません。
両者の違いに関しては数え切れないほどのブログ記事が存在するので、時間を見つけて机の前に座り、読んで、練習をこなしていきましょう。
以下の質問には答えられるようにしておきましょう。
- 配列を走査する方法は? その方法はオブジェクトにも使えますか?もしできるとして、そうすべきでしょうか?
- オブジェクトを走査する方法は? その方法は配列にも使えますか?もしできるとして、そうすべきでしょうか?
- オブジェクトの値にアクセスする方法は? 配列の場合は?
- あるオブジェクトの値を見つけたいとして、そのキーがわかる場合、どのようにすれば見つかるでしょうか? キーがわからない場合はどうすればいいでしょう?
- オブジェクトと配列の違いを見分けるためには、どんなコードを書けばよいですか?
注:もしもprototype
やthis
について言及している記事を見かけた場合は、いったんその部分を読み飛ばすのも手です。つまづきやすい重要なコンセプトであることには変わりありませんが、コードクリサリスのテクニカル・インタビューでこれらについて問うことはないので、後日の学習に回しておきましょう。まずは基本を固めることに集中してください。
参考
- Eloquent JavaScript Chapter 4 Data Structures
- Scotch.io Data Structures: Objects and Arrays
- MDN Array documentation
7. 表示されている内容を読んでいないか、十分に吟味していない
イマーシブコースの選考プロセスで出されるコーディング・チャレンジでは、みなさんが書く関数のインプットやアウトプットについて非常に厳密な要求が課されています。
コードのロジックに手を出す前に、必ずどのような関数を要求されているのか整理しましょう。
function nameOfFunctionHere(/* いま問われているインプットは? */) {
return /* (もし存在するなら)どのようなアウトプットが必要か? */
}
もし問題の意図がよくわからなければ、聞いて確かめましょう!
要求されている関数の大枠がはっきりしたら、ロジックに移りましょう。次のような質問に自分で答えていってみましょう。
- 後で使う必要があるもののために、それを格納する変数を宣言しないといけないだろうか?
- なにかループする必要があるものはあるか?
- 現時点でアクセスできる変数や情報は何か?
8. JavaScriptにおける関数は値であるということ
関数はJavaScriptにおける値の一種にすぎません。JavaScriptの値には、たとえばどんなものがあるでしょうか?
以下は、ごく基本的なデータ型とその例です(一覧を見たい方は、下記のリンクを参照してください)。
type: examples
- number: 1, 0, 1.01, -5
- string: "@nything", '1n quotes!&^#W?'
- boolean: true, false
- undefined: undefined
- object: {}, []
- function: function myFuncName() {}
これらは値として、変数に格納することができます。
let myNumber = 10;
let myString = ‘Hello!’;
let myBoolean = true;
let myUndefined; // ← なぜmyUndefinedには何も代入しなくて良いのでしょうか?
let myObject = {a: 1, b: 2};
let myFunction = function() {
return ‘This is my function output!’;
};
補足: 関数を定義したいとき、上記のように関数式(function expression)として書くことができることに注意しましょう。上の例では、関数がmyFunction
という変数に代入されていますね。関数を定義する際は、次の例のように関数宣言(function declaration)として書くこともできます。
function myFunction() {
return ‘This is my function output!’;
}
この2つはほぼ同じ挙動をします。両者の違いについて興味のある方は巻き上げについて読んでみてください。ただし、この相違点に関しては現時点で知っておく必要はありません。
return
キーワードを使うことで、これらの値を関数から「リターン」することもできます(アウトプットがそれですね!)。
function getNumber() {
return 10;
}
function getString() {
return ‘Hello!’;
}
function getBoolean() {
return true;
}
function getUndefined() {
}
function getObject() {
return {a: 1, b: 2};
}
関数自体を関数から返すことも可能です。
function getFunction() {
return function() {
return ‘This is my function\’s function output!’;
}
}
上記の関数に、 `This is my function\’s function output!’ を表示させるにはどうすればよいでしょうか?
以下のコードをコンソールで実行してみてください。ただし、実行する前に、次の質問の答えを考えてみましょう。
- 何が表示されると思いますか?
- `typeof whatIsThis’ は何を返すでしょうか?
- このコードで
whatIsThis()
に相当する値は何でしょうか?
getFunction();
getFunction()();
let whatIsThis = getFunction();
console.log(typeof whatIsThis);
whatIsThis();
参考
9. エラーメッセージを読んでいない
エラーメッセージはみなさんの親友です!頻繁に出くわすエラーメッセージに慣れて、その意味がわかるようになりましょう。無視するのはご法度です。
エラーメッセージは、エラーの内容だけでなく、エラーが発生したコードの行番号も教えてくれます。これらに細心の注意を払って、その意味をGoogleで調べる習慣を身につけましょう。
初心者プログラマがよく出くわすエラーメッセージの例
Uncaught ReferenceError: _______ is not defined
これは変数や関数の名前が見つからないときによく出てくるメッセージです。JavaScriptエンジンは、その名前が何を指しているのか理解できていない、というわけです。
スペルの誤りはないでしょうか? 変数は全て宣言されていますか? コピペしたりしませんでしたか?(内容を理解せずにコピペするのはやめましょう)
Uncaught SyntaxError: Function statements require a function name
Uncaught SyntaxError: Unexpected identifier
カッコで始めたり、カッコを閉じたりするのを忘れてはいませんか? これは大概そういったときに出てくるエラーです。
Uncaught TypeError: Cannot read property
これは大抵、定義されていないオブジェクトに対しプロパティを読み込もうとしたり、メソッドを呼び出そうとしたりしたときに表示されるエラーです。オブジェクトに存在しないメソッドを使おうとはしていませんか? そもそもそのオブジェクトは定義されていますか?
参考
10. 確認不足とテスト不足〜コードを十分に実行していない
コードを書くときは、遠慮せずにconsole.log
で変数をコンソールに表示しましょう。このテクニカル・インタビューでは、何度コードを実行しても大丈夫です。あなたの仮説を実証するためにコードを実行しましょう。本当にその変数の中身は関数でしょうか? それとも文字列? 数値型?
あなたが 2
だと思っていたものが実際には ’2’
だったりすると、それは結果に大きな違いを生みがちです。console.log
やtypeof
を使って、あなたの考えが考えで終わらず、実際に正しいことをダブルチェックしておきましょう。
この習慣は、バグを防ぐことにも繋がります。たくさんのコードを書き終えて最後に実行したとき、初めて間違っているものがあると気づくようでは、イライラするかもしれませんよね。そんな間違いを犯す事態に陥らないよう、バグから自分自身を守りましょう。
ハッピー・コーディング!
もっと知りたいという方は、こちら