1
1

僕のJavascriptの初耳な仕様

Last updated at Posted at 2024-06-09

筆者と当記事を書き始めた経緯について

当方、資格集めが趣味のエンジニアです。
資格の保有数は20種類に到達したんですが、いまだにJS関連の資格は持っていないし、仕事でVue.jsを書いたりすることもあるものの、JSがそんな得意なわけでもないといったところでJS系の資格の取得を検討しております。
一応、今狙ってるのはJS InstituteのJSE – Certified Entry-Level JavaScript Programmer Certificationという資格です。
こちらはめちゃくちゃ初学者向けの資格なんですが、受けられる言語が英語しかないので、英語のお勉強も兼ねてひとまずこの資格をターゲットとすることにしました。

JS自体は個人的な感覚にもなりますが、そこまで特殊な言語ではない(筆者が一番多用するのはJavaなので、無意識にJavaと比較してます)と思うんですが、それでも
「こんな仕様があるんだなぁ」
と勉強しながら思うことがあるので、忘れないうちに記載していこうと思います。

「いやいや、そんなんJS的には周知の挙動でしょ。つか、他の言語でも普通にある仕様でしょ。」と思われるかもしれませんが、ご容赦を。

当記事について

こちらの教材を使って勉強しているんですが、まだまだ教材を1周もしきってないので、初見の仕様に出くわす度に当記事は更新していこうと思います。

初見だったJavascriptの仕様

Hoisting

Hoisting MDN
Hoisting、和訳すると巻き上げとなるそうですが、これは
varで変数を宣言した場合に、その変数の宣言は当該変数の属するスコープの先頭にリライトされることだそうです。

なので例えば、
下記のhoisting1.jshoisting2.jsは両方ともweightを参照した際にReferenceErrorを発生させるように見えますが、

hoisting1.js
var height = 180;
console.log(height);
console.log(weight);
hoisting2.js
var height = 180;
console.log(height);
console.log(weight);
var weight = 70;
console.log(weight);

実際の挙動は異なり、hoisting2.jsは実際に実行されるソースは下記のようになるため実際にはhoisting2.jsに限っては、undefinedとコンソールに出力されることになります。

hoisting2_execute.js
var height = 180;
var weight;
console.log(height);
console.log(weight);
weight = 70;
console.log(weight);

単項プラス

単項プラス演算子 MDN
皆さんは↓のソースの計算結果わかります?

plus1.js
const str1 = 42 + "1";

他の言語でもそうですが、文字列と何かを+演算子にかけると計算対象の値の両方が文字列として評価されます。
なので上記の計算結果は421となります。
では"1"を数値として扱って43という計算結果を得るためにはどうしたらいいでしょう?

素直に考えたら

plus2.js
const str1 = 42 + Number("1");

が一番パッと出てくる解だと思いますが、実は↓でも同様の解を得られます。

plus3.js
const str1 = 42 + +"1";

僕は最初見たとき意味が分からなかったんですが、こちらはJavascriptの単項プラス演算子による働きのためによるものです。

単項プラス演算子は直後の値をNumber型に変換します。
そのため"1"Number型になることで43という解を得ることができるようになります。

因みに+"あ"みたいなNumberに変換できない値を引数として受けた場合はNaNが戻り値となります。

Boolean型の複合代入演算子

他の言語でもよくある仕様なのか、これまで実務で使ったことないからわからないんですが、複合代入でよく使うのは数値型(JavascriptならNumber)での複合代入だと思います。

compoundAssignment1.js
let compoundAssignmentNum = 1;
    compoundAssignmentNum += 1 // compoundAssignmentNum === 2

これは実務でも8000万回くらいつかってきたんですが、同様に複合代入がBooleanでも行えます。

compoundAssignment2.js
let compoundAssignmentBool = true;
compoundAssignmentBool &= false; // compoundAssignmentBool === false

// もちろんショートサーキットもいける
let compoundAssignmentBool = true;
compoundAssignmentBool &&= false; // compoundAssignmentBool === false

// ORも同様
let compoundAssignmentBool = true;
compoundAssignmentBool ||= false; // compoundAssignmentBool === true

論理積、論理和の戻り値

論理積 MDN
論理和 MDN
&&(論理積)や||(論理和)の戻り値は

  • &&:両方のオペランドがtrueの場合にtrueを返却する、その他の場合はfalseを返却する。
  • ||:両方のオペランドがfalseの場合にfalseを返却する、その他の場合はtrueを返却する。

と認識していましたが、正確には挙動は少し違くて

  • &&:最初に遭遇したfalsyなオペランドの値を返却し、すべてがtruthyな値の場合には最後のオペランドの値を返却する。
  • ||:最初のオペランドがtruthyな値の値の場合には、最初のオペランドの値を返却する。そのほかの場合は、2つ目のオペランドの値を返却する。

「いやいや、元々の解釈と何が違うのよ。一緒じゃん。」
と思うかもしれませんが、truthyな値falsyな値ってのが、ミソなんですねぇ。

オペランドがBoolean型の値なら想定通りの挙動なんです。

andOr1.js
console.log(true && true); // --> true
console.log(true || false); // --> true

しかしながら、javascriptは以下の値をfalsyな値(≒false)として扱います。

  • false
  • null
  • NaN
  • 0
  • 空文字列 ("" または '' または ``)
  • undefined

加えて、論理積、論理和が返却するのは、Boolean型の値ではなく、あくまでオペランドの値です。
なのでオペランドがBoolean型の値でない場合は以下のような戻り値を返却することになります。

andOr2.js
console.log("Hello" && "World"); // --> "World"
console.log(1 && 2); // --> 2
console.log("Hello" || "World") // --> "Hello"
console.log(1 || 0); // --> 1

Booleantruefalsetruthyfalsy、ここら辺の解釈が厄介ですね。

でも今思うと、javascriptで空文字のチェックってif(string/*string型の変数*/)とかでやってて、javascriptで空文字はfalsyな値だから、先ほどのif文は空文字のチェックができるみたいなことを8000万回くらいやってたから、よくよく考えてみたらこのトピックの一部は既知の内容だったかもですね。

IIFE

IIFE MDN
こちらは、Immediately Invoked Function Expression、略してIIFEです。
和名だと単純に即時実行関数式となります。
例えば↓です。

iife1.js
(function(){
    let a = 'II';
    let b = 'FE';
    console.log(`${a}${b}`);
})();

関数を宣言すると同時に即時実行しています。
もちろん、アロー関数も使えます。

iife2.js
(() => {
    let a = 'II';
    let b = 'FE';
    console.log(`${a}${b}`);
})();
1
1
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
1
1