こんにちは。この記事はSalesforce 開発者向けブログ投稿キャンペーンへのエントリー記事です。
テーマは [2] Salesforce のコーディング開発
です。
はじめに
日本語試験が公開されたばかりの Salesforce 認定 JavaScript デベロッパー に挑戦中です。
日本語のガイド: https://tandc.salesforce.com/examguide_cert_javascript_developer.pdf
このエントリを書いている 2020年11月時点で 1回落ちていますので、次は2回目の挑戦になります。
1回目は2020年11月に受験(正答率:60%)。
ボーダラインは 65% ですので、あと一息です。次こそ合格するべく、苦手な単元を整理していきたいと思います。
苦手な単元
1回目の試験結果を見ると、ボーダラインに達していない(あるいはギリギリの)単元が 4 つありました。
- 【57%】(8/14) Variables, Types, and Collections (変数、データ型、コレクション)
- 【66%】(10/15) Objects, Functions, and Classes (オブジェクト、関数、クラス)
- 【40%】(4/10) Browser and Events (ブラウザとイベント)
- 【37%】(3/8) Asynchronous Programming (非同期プログラミング)
試験はほぼ全てコードリーディングです。普段書き慣れてない書き方が多く、結構戸惑いました。
受験ガイドの試験範囲を見ながらキーワードを深掘りしていきます。
1. 変数、データ型、コレクション
出題内容
- シナリオに基づき、変数を作成して正しく初期化するコードを記述する。
- ビジネス要件に基づき、文字列、数値、日付を効果的に利用する。
- シナリオまたは例に基づき、型強制とその影響を認識していることを示す。
- 特定のシナリオに基づき、truthy または falsey な評価を区別する。
- データのリストに基づき、配列を使用したデータ操作を示す。
- JSON 応答に基づき、JSON オブジェクトの操作方法を示す。
Number
- JavaScript の数値は
Number
とBigInt
のみ。- Float (32 bit) も Double (64 bit) も
Number
- Float (32 bit) も Double (64 bit) も
- $1.8 \times 10^{308}$ より大きいと
Infinity
に解釈される。 - 渡された値が NaN かどうかを判定する:
Number.isNaN()
- 渡された値が有限数かどうかを判定する:
Number.isFinite()
- 渡された値が整数かどうかを判定する:
Number.isInteger()
// true は 1 と同じ
(true + 1 + '10') * 2 // 210 * 2 = 420
// 文字列を数字に変換する。
Number('12345') // 12345
NaN (Non-A-Number)
-
NaN
になるもの
const value = NaN;
value !== value // NaN
Number(undefined) // NaN
Number('zero') // NaN
Number(0/0) // NaN
Number(1/'zero') // NaN
Number('zero'/0) // NaN
parseInt("zero") // NaN
Math.sqrt(-1) // NaN
0 * Infinity // NaN
NaN === NaN; // false
Number.isNaN(NaN); // true
Object.is(value, NaN) // true
-
NaN
にならないもの
Number(1/0) // Infinity
Number(1/'0') // Infinity
reduce()
-
accumulator
: callback の返り値を蓄積するアキュームレーター -
currentValue
: 現在処理されている配列の要素 -
initialValue
: 返り値の初期値
const array = [1, 2, 3, 4, 5];
const initialValue = 10;
const newArray1 = array.reduce((accumulator, currentValue) => {
return accumulator + currentValue;
});
console.log(newArray1); // 15
const newArray2 = array.reduce((accumulator, currentValue) => {
return accumulator + currentValue;
}, initialValue);
console.log(newArray2); // 25
splice()
既存の要素を取り除いたり、置き換えたり、新しい要素を追加したりできる。
const array = ['A0', 'B1', 'C2', 'D3', 'E4', 'F5', 'G6', 'H7'];
const start = 3;
const deleteCount = 2;
const item1 = 4
const newArray = array.splice(start, deleteCount, item1);
console.log(newArray); // ["D3", "E4"]
console.log(array); // ["A0", "B1", "C2", 4, "F5", "G6", "H7"]
slice()
start から end まで (end は含まれない) で選択された配列の一部を返す。
const array = ['A0', 'B1', 'C2', 'D3', 'E4', 'F5', 'G6', 'H7'];
const start = 3;
const end = 6;
const newArray1 = array.slice(start);
const newArray2 = array.slice(start, end);
console.log(newArray1); // ["D3", "E4", "F5", "G6", "H7"]
console.log(newArray2); // ["D3", "E4", "F5"]
console.log(array); // ["A0", "B1", "C2", "D3", "E4", "F5", "G6", "H7"]
for (...) {}
in
なのか of
なのかで結果が違うので注意する。
const items = [{name: 'a'}, {name: 'b'}, {name: 'c'}];
for (let item in items) {
console.log(item); // 0, 1, 2
console.log(items[item]); // {name: 'a'}, {name: 'b'}, {name: 'c'}
console.log(items[item].name); // a, b, c
}
for (let item of items) {
console.log(item); // {name: 'a'}, {name: 'b'}, {name: 'c'}
console.log(item.name); // a, b, c
}
Object.assign()
値を上書きする。
const target = { a: 1, b: 2 };
const source = { b: 0, c: 3 };
console.log(Object.assign(target, source)); // { a: 1, b: 0, c: 3 }
Object.freeze()
値を更新も追加もできないようにロックする。
const target = { a: 1, b: 2 };
Object.freeze(target);
target.a = 0;
target.c = 3;
console.log(target); // { a: 1, b: 2 }
Object.seal()
値を追加できないようにロックする。更新は可能。
const target = { a: 1, b: 2 };
Object.seal(target);
target.a = 0;
target.c = 3;
console.log(target); // { a: 0, b: 2 }
Object.preventExtensions()
オブジェクトのさらなる拡張を抑制する。
const obj = {};
obj.name = 'A';
Object.preventExtensions(obj);
obj.title = 'B';
console.log(obj); // { name: "A" }
2. オブジェクト、関数、クラス
出題内容
- ビジネス要件に基づき、最良の関数実装を見つける。
- ビジネス要件に基づき、オブジェクト実装の基本を適用し、ビジネス要件を解決する。
- ビジネス要件に基づき、クラス実装の基本を適用し、ビジネス要件を解決する。
- 与えられた JavaScript モジュールで、モジュールの使用方法の例を示す。
- 与えられた JavaScript デコレータで、デコレータの使用方法の例を示す。
- 与えられたコードブロックで、変数のスコープと実行フローを分析する。
コンストラクタの定義
- クラスで定義する時には
constructor
を使う。 - 関数で定義する時には、関数名と同じにする。
class Person {
constructor(name) {
this.name = name;
}
sayHello() {
console.log(`Hello, ${this.name}`);
}
}
const taro = new Person('Taro');
taro.sayHello(); // "Hello, Taro"
function Person(name) {
this.name = name;
this.sayHello = function() {
console.log(`Hello, ${this.name}`);
}
}
const taro = new Person('Taro');
taro.sayHello(); // "Hello, Taro"
3. ブラウザとイベント
出題内容
- ビジネス要件に基づき、イベント、イベントハンドラー、イベント伝達を利用する。
- ビジネス要件に基づき、DOM を評価および操作する。
- シナリオに基づき、ブラウザ開発ツールを利用してコードの動作を調査する。
- シナリオと要件に基づき、ブラウザ固有の API を利用する。
style.display
非表示にしたい場合は hidden ではなく none
を代入する。
<div id="sample">Sample</div>
// 非表示
document.getElementById("sample").style.display = "none";
// 表示
document.getElementById("sample").style.display = "block";
addEventListener()
特定のイベントごとに呼び出される関数を定義する。
<a class="clickOnce" href="https://www.mozilla.org" target="_blank">Click Once</a>
const clickOnce = document.querySelector('.clickOnce');
// ページの DOM が読み込まれたら実行したい場合は "DOMContentLoaded" を定義する
window.addEventListener('DOMContentLoaded', (event) => {
console.log('DOM fully loaded and parsed');
});
// 画像など全てのリソースが読み込まれてから実行したい場合は "load" を定義する
window.addEventListener('load', (event) => {
console.log('ページが完全に読み込まれました');
});
// "onload" でも同じ
window.onload = (event) => {
console.log('ページが完全に読み込まれました');
};
// 1回切りにしたい場合は、オプションの "once" を指定する
clickOnce.addEventListener('click', function(event) {
console.log('clicked!');
}, { once : true });
// イベントが伝播するのをブロックしたい場合は、"stopPropagation" を呼ぶ
clickOnce.addEventListener('click', function(event) {
event.stopPropagation();
console.log('clicked!');
}, { once : true });
// 規定の動作をブロックしたい場合は、"preventDefault" を呼ぶ
clickOnce.addEventListener('click', function(event) {
event.preventDefault();
alert('You cannot click me!');
});
CustomEvent
detail
プロパティを使用してカスタムデータを渡すことができる。
const event = new CustomEvent("sample", {
detail: {
recordId: '12345'
}
});
Node.js のデバッグ起動
node --inspect index.js
console.table()
console.table()
この機能は標準ではなく、標準化の予定もありません
- 表形式のデータを表で表示する。
- 列のソートも可能。
console.table(["apples", "oranges", "bananas"]);
4. 非同期プログラミング
出題内容
- シナリオに基づき、非同期プログラミングの概念を適用する。
- シナリオに基づき、イベントループとイベント監視を使用する、またはループの結果を判断する。
setTimeout
遅延時間に 0
を設定しても、実際には最低 4 ミリ秒の遅延がある。
console.log('1');
setTimeout(() => {
console.log('3');
}, 0);
console.log('2'); // 1, 2, 3
setInterval
setTimeout
と共存する場合は、遅延時間に注目する。
console.log('1');
setTimeout(() => {
console.log('3');
}, 1100);
console.log('2');
const timerId = setInterval(() => {
console.log('A');
}, 1000);
setTimeout(() => {
clearInterval(timerId);
console.log('stop');
}, 3000); // 1, 2, A, 3, A, A, stop
Promise
- Promise の状態(States)は 3 つのみ。
- 待機
pending
:初期状態。成功も失敗もしていない。 - 満足
fulfilled
:処理が成功して完了。 - 拒絶
rejected
:処理が失敗。 -
fulfilled
かrejected
かのどちらかになった状態(pending
ではない状態)をsettled
と呼ぶ。
- 待機
- Promise の運命(Fates)は 2 つのみ。
- 解決
resolved
:fulfilled
かrejected
かのどちらかになることが決まっている。 - 未解決
unresolved
:fulfilled
かrejected
かのどちらかになることが決まっていない(pending
)。
- 解決
-
then(...).catch(...).finally(...)
でつなぐ。
const promise1 = new Promise((resolve, reject) => {
setTimeout(resolve, 500, 'one');
});
const promise2 = new Promise((resolve, reject) => {
setTimeout(resolve, 100, 'two');
});
const promise3 = Promise.resolve(3);
const promise4 = 4;
// 先に解決した方が勝ち: "race"
Promise.race([promise1, promise2])
.then((value) => {
console.log(value);
}); // two
Promise.race([promise1, promise2, promise3, promise4])
.then((value) => {
console.log(value);
}); // 3
// 全部解決するまで待つ: "all"
Promise.all([promise1, promise2, promise3, promise4])
.then((value) => {
console.log(value);
}); // [one, two, 3, 4]
const onFulfilled = (result) => {
console.log(result);
};
const onRejected = (result) => {
console.error(result);
};
// 引数で与えられた理由で解決された Promise オブジェクトを返す
Promise.resolve('Success')
.then(onFulfilled, onRejected); // Success
// 引数で与えられた理由で拒絶された Promise オブジェクトを返す
Promise.reject(new Error('Fail'))
.then(onFulfilled, onRejected); // Error: Fail
Promise.reject(new Error('Fail'))
.catch((result) => {
console.error('result - ' + result)
}); // result - Error: Fail
debounce()
- 最後に受け付けた第1引数の関数のみを発動する。
- 第2引数の時間の間は関数を受け付けない。
- 第3引数に true が設定された時は即時発動する。
_.debounce = function(func, wait, immediate) {...}
参考文献
そのほか、試験勉強で利用したサイトです。
- Prepare for your Salesforce JavaScript Developer I Credential
- Study for the Salesforce JavaScript Developer I Exam
さいごに
多肢選択式試験に関しては、Salesforce の知識は全然必要ありませんでした。
みなさんもぜひ挑戦してください!
それではまたお会いしましょう。
おまけ
試験の結果は...
2020年12月に合格しました