41
36

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Salesforce 認定 JavaScript デベロッパー試験の個人的な躓きポイント

Last updated at Posted at 2020-12-01

こんにちは。この記事はSalesforce 開発者向けブログ投稿キャンペーンへのエントリー記事です。
テーマは [2] Salesforce のコーディング開発 です。

:pencil: Salesforce 開発者向けブログ投稿キャンペーン 第4弾

はじめに

日本語試験が公開されたばかりの Salesforce 認定 JavaScript デベロッパー に挑戦中です。

日本語のガイド: https://tandc.salesforce.com/examguide_cert_javascript_developer.pdf

このエントリを書いている 2020年11月時点で 1回落ちていますので、次は2回目の挑戦になります。

1回目は2020年11月に受験(正答率:60%)。
ボーダラインは 65% ですので、あと一息です。次こそ合格するべく、苦手な単元を整理していきたいと思います。

苦手な単元

1回目の試験結果を見ると、ボーダラインに達していない(あるいはギリギリの)単元が 4 つありました。

  1. 【57%】(8/14) Variables, Types, and Collections (変数、データ型、コレクション)
  2. 【66%】(10/15) Objects, Functions, and Classes (オブジェクト、関数、クラス)
  3. 【40%】(4/10) Browser and Events (ブラウザとイベント)
  4. 【37%】(3/8) Asynchronous Programming (非同期プログラミング)

試験はほぼ全てコードリーディングです。普段書き慣れてない書き方が多く、結構戸惑いました。
受験ガイドの試験範囲を見ながらキーワードを深掘りしていきます。


1. 変数、データ型、コレクション

出題内容

  • シナリオに基づき、変数を作成して正しく初期化するコードを記述する。
  • ビジネス要件に基づき、文字列、数値、日付を効果的に利用する。
  • シナリオまたは例に基づき、型強制とその影響を認識していることを示す。
  • 特定のシナリオに基づき、truthy または falsey な評価を区別する。
  • データのリストに基づき、配列を使用したデータ操作を示す。
  • JSON 応答に基づき、JSON オブジェクトの操作方法を示す。

Number

:bookmark: Number

  • JavaScript の数値は NumberBigInt のみ。
    • Float (32 bit) も Double (64 bit) も Number
  • $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)

:bookmark: NaN

  • 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()

:bookmark: Array.prototype.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()

:bookmark: Array.prototype.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()

:bookmark: Array.prototype.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 (...) {}

:bookmark: ループと反復処理

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()

:bookmark: 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()

:bookmark: 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()

:bookmark: 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()

:bookmark: 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()

:bookmark: addEventListener()
:bookmark: Window: load イベント

特定のイベントごとに呼び出される関数を定義する。

<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

:bookmark: CustomEvent()
:bookmark: イベントの作成と起動

detail プロパティを使用してカスタムデータを渡すことができる。

const event = new CustomEvent("sample", {
  detail: {
    recordId: '12345'
  }
});

Node.js のデバッグ起動

:bookmark: インスペクタを有効にする

node --inspect index.js

console.table()

:bookmark: 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

:bookmark: Promise
:bookmark: States and Fates

  • Promise の状態(States)は 3 つのみ。
    • 待機 pending:初期状態。成功も失敗もしていない。
    • 満足 fulfilled:処理が成功して完了。
    • 拒絶 rejected:処理が失敗。
    • fulfilledrejected かのどちらかになった状態(pending ではない状態)を settled と呼ぶ。
  • Promise の運命(Fates)は 2 つのみ。
    • 解決 resolvedfulfilledrejected かのどちらかになることが決まっている。
    • 未解決 unresolvedfulfilledrejected かのどちらかになることが決まっていない(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()

:bookmark: debounce()

  • 最後に受け付けた第1引数の関数のみを発動する。
  • 第2引数の時間の間は関数を受け付けない。
  • 第3引数に true が設定された時は即時発動する。
_.debounce = function(func, wait, immediate) {...}

参考文献

そのほか、試験勉強で利用したサイトです。

さいごに

多肢選択式試験に関しては、Salesforce の知識は全然必要ありませんでした。
みなさんもぜひ挑戦してください!

それではまたお会いしましょう。

おまけ

試験の結果は...
2020年12月に合格しました:sunny:

41
36
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
41
36

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?