Help us understand the problem. What is going on with this article?

【初心者用】クイズJavaScript

はじめに

JavaScript初心者向けのクイズ記事です!

内容は主に、JavaScript本格入門 モダンスタイルによる基礎から現場での応用まで を参考にさせていただいています。
JavaScript本格入門 モダンスタイルによる基礎から現場での応用まで

第1問 function命令

どちらが正しく動作する?

(1)
console.log(getHello());

function getHello(){
  return "Hello!";
}
(2)
console.log(getHello());

let getHello = function(){
  return "Hello!";
}

正解

(1)

理由

function命令はどのタイミングで登録されるのでしょうか。
ズバリ、コードをコンパイルするタイミングでfunction命令の関数は登録されます。
つまり、(1)はconsole.logでgetHelloを呼び出していますが、その時点で関数が登録されているのです。

一方(2)は関数リテラルです。
このコードの結果は、「そんな関数登録されてねーよ」と怒られます。
つまり、function命令とは登録されるタイミングが違います。
関数リテラルは、代入されたタイミングで登録されます。
その結果、(2)のコードは正常に動作しないのです!

第2問 変数の巻き上げ

次のコードの実行結果は次のうちどれ?
(1)Global, Local
(2)Local, Local
(3)undefined, Local

var value = 'Global';

function func(){
  console.log(value);
  var value = 'Local';
  console.log(value);
}

func()

正解

(3)

理由

JavaScriptの変数巻き上げ問題です。
一番多い間違いはおそらく(1)だと思います。
JavaScriptでない言語であればそうなるかもしれないです。
しかしJavaScriptでは、
関数内で定義されているローカル変数は、関数の先頭で宣言されたものとする
という意味のわからないルールがあります。

つまり、上のコードは

var value = 'Global';

function func(){
  var value;

  console.log(value);
  var value = 'Local';
  console.log(value);
}

func()

このコードと等しくなります。
これを見ると、関数内のvalueには何も代入されていないのでundefinedになる理由もわかると思います。

第3問 参照型

次のコードの正しい結果はどっち?
(1)[1,2,3,4,5]
(2)[1,2,3,4]

var value = [1,2,3,4,5];

function deleteElement(value){
  value.pop();
  return value;
}

deleteElement(value);
console.log(value);

正解

(2)

理由

配列は参照型です。
参照型とは、値そのものではなく値に格納したメモリ上の場所を格納している型です。
つまり、引数に参照型であるvalueを渡すと、仮引数のvalueは値を格納したメモリ上の場所を渡されることになります。(参照渡し)
その結果、関数の中で配列を操作するとその結果はグローバル変数であるvalueにも反映されることになるのです!

第4問 デフォルト値

次のコードの正しい結果はどれ?
(1)NaN
(2)11
(3)10

function getSum(x = 1, y){
  return x + y;
}

console.log(getSum(10));

正解

(1)

理由

まずはじめに言いたいのは、デフォルト値をもつ仮引数は、引数リストの末尾に集めておくべきという点です。
今回のコードは、知らないとxが1、yが10となり答えが11になる、と考えてしまうかもしれませんが、
実際にはxに引数である10、yはデフォルト値を持たずundefinedとなり、結果として NaNとなります。

yに10を入れたい場合は、

function getSum(y, x = 1){
  return x + y;
}

とすべきですね。

第5問 this

次のコードの正しい結果はどれ?
(1)エラー
(2)Taro Script, undefined undefined
(3)Taro Script, Taro Script

let myIntro = {
    firstName: "Taro",
    lastName: "Script",
    getFullName: function(){
        console.log(this.firstName + " " + this.lastName);

        function getString(){
            console.log(this.firstName + " " + this.lastName);
        }

        getString();
    }
}

myIntro.getFullName();

正解

(2)

理由

JavaScriptのthisは初心者にとって本当にややこしいですね。
ここではまずわかりやすい問題でthisに慣れていきましょう。
まず一つ目のconsole.log内のthisはメソッド呼び出しのためmyIntroになっています。
そして次が問題です、メソッドの中の関数呼び出し内のthisは何を指すのでしょうか。
試しに見てみましょう。

let myIntro = {
    firstName: "Taro",
    lastName: "Script",
    getFullName: function(){
        //console.log(this.firstName + " " + this.lastName);

        function getString(){
            console.log(this);
            //console.log(this.firstName + " " + this.lastName);
        }

        getString();
    }
}

myIntro.getFullName();

このlogには、

Object [global] {
  global: [Circular],
  .....
  .....
}

はい、グローバルオブジェクトを指しています。
そのため、このクイズの答えはundifinedになってしまうわけです。
こうなってしまった場合には、オブジェクト内でthisを別の変数に格納するしかありません。

let myIntro = {
    firstName: "Taro",
    lastName: "Script";
    getFullName: function(){
        console.log(this.firstName + " " + this.lastName);
        let self = this;

        function getString(){
            console.log(self.firstName + " " + self.lastName);
        }

        getString();
    }
}

myIntro.getFullName();

第6問 アロー関数

次のコードの正しい結果はどれ?
(1)エラー
(2)Taro Script, undefined undefined
(3)Taro Script, Taro Script

let myIntro = {
    firstName: "Taro",
    lastName: "Script",
    getFullName: function(){
        console.log(this.firstName + " " + this.lastName);

        let getString = () => {
            console.log(this.firstName + " " + this.lastName);
        }

        getString();
    }
}

myIntro.getFullName();

答え

(3)

理由

先ほどの問題の続きです。
今回はメソッド内の関数呼び出しにアロー関数を用いています。
アロー関数の優れている点は、まずはコードがシンプルになることです。
しかし、それだけではありません。

アロー関数内のthisはどこのオブジェクトを見るのでしょう。
答えは、まずアロー関数内に参照できるオブジェクトがないか探します。
そして、ない場合は関数の1つ外側のオブジェクトを参照します
今回の問題でいうと、getFullNameのthisを参照することになるため、答えは(3)となります。

第7問 配列

次のコードの正しい結果はどっち?
(1)5
(2)102

let ary = [1,2,3];
ary[3] = 4;
ary[100] = 100;
ary.push("test");

console.log(ary.length);

答え

(2)

理由

配列.lengthは一番大きい添え字に+1をした数が返ってきます。
この場合、要素4番目~99番目までのメモリは確保されますが、値が入っておらずundefinedになり、100番目に100が代入されます。
そして、pushにより101番目にtestが代入されます。
よって、答えは最後にpushをしたtestの添え字101+1になります。

おしまい

ない知識を振り絞って作ってみた7問です。
正直に言うと最近JavaScriptを勉強しはじめたばかりなので、間違い等あれば教えていただきたいです。

最後にもう一度。
JavaScriptを勉強するなら、JavaScript本格入門(特に4章と5章)最高ですよ。

JavaScript本格入門 モダンスタイルによる基礎から現場での応用まで

あとMDNも読みましょうね。

JavaScript | MDN

hcr1s
JavaScript(NodeJS) / React / AWS(Lambda, DynamoDB) あたりを記事にしていきたい
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away