LoginSignup
0
1

More than 3 years have passed since last update.

【JS】JSを根本から再復習、スコープとかクロージャーとか

Last updated at Posted at 2020-08-05

JS(VueやReact)をなんとなく使ってしまっているので、色々学習しています。
この記事は下記コースのアウトプットになります。
【JS】初級者から中級者になるためのJavaScriptメカニズム | Udemy

スコープ

  • グローバルスコープ
  • スクリプトスコープ
  • 関数スコープ
  • ブロックスコープ
  • モジュールスコープ

グローバルスコープ

windowsオブジェクト = グローバルスコープ

関数スコープ

function scope() {
  // ここに囲まれたスコープのこと指します
}

ブロックスコープ

{}で囲まれた範囲のことを指します。
varを使った場合は、ブロックスコープは生成されません。
var,let,constの違いは、ブロックスコープと巻き上げ - 30歳からのプログラミング

レキシカルスコープ(外部スコープ)

実行中のコードから見た外部のスコープのことを指します。
image.png

// 下記の場合、関数 a がレキシカルスコープになります。
function a() {
  function b() {
    console.log('だだだだだ')
  }
}

クロージャー

レキシカルスコープを関数として使用している状態のことをさします。

// 下記のような状態のこと
function soto() {
  let aaa = "test"
  function uchi() {
    console.log(aaa)
  }
}

プライベート変数を設定する

外部からアクセスできない変数を定義します。

function incrementFactory() {
    // 外部からアクセスできない変数
    let num = 0;
    function add() {
        num += 1;
        console.log(num);
    }
    // 関数addを返している
    return add;
}

// 変数に関数の実行を定義する
const increment = incrementFactory();

increment(); // 1
increment(); // 2

// プライベート担っているため、外部からは呼び出せない
console.log(num) // エラー

動的な関数

function addNumberFactory(num) {
    function addNumber(value) {
        return num + value;
    }
    return addNumber;
}

const add5 = addNumberFactory(5);
const add10 = addNumberFactory(10);
const result = add10(10);
console.log(result);

あとこんな書き方もできます。知らんんかった、、、

function factory(val) {
    return {
        plus: function(target) {
            const newVal = val + target;
            console.log(`${val} + ${target} = ${newVal}`);
            val = newVal;
        },
        minus: function(target) {
            const newVal = val - target;
            console.log(`${val} - ${target} = ${newVal}`);
            val = newVal;
        },
    };
}

const cal = factory(10);
cal.plus(5);
cal.minus(5);

即時関数

関数定義と同時に一度だけ実行される関数のことをさします。

実装は以下のようになります。
最初のカッコは、グループ化をさし、次のカッコは、関数の実行のことをさします。
基本的に function には名前をつけなければいけないので、()を外したらエラーになります。

// 通常の関数
function test() {
  console.log('called');
}

// 即時関数
(function() {
  console.log('called');
})()

// 変数に入れる場合は、
const c = (function() {
  let val = 10;

  function fn() {
    console.log('fn is called');
  }

  return {
    val,
    fn
  };
})()

// 関数の呼び方
c.fn();
// 変数の呼び出し方
console.log(c.val);

暗黙的な型変換

変数が呼ばれた状況によって、変数の型が自動的に変換されるので、覚えておく。

プリミティブとオブジェクト

プリミティブ

オブジェクト以外の物を全て指します。
具体的には、 String, Null, Symbolなどですね。
イミュータブルで、再代入の場合は、値の参照が切り替わります。

コピー

参照先の値がコピーされます。
元の変数を変更しても、元の変数、代入した変数は独立しているので、値は変わりません。

// address に a という変数を使って、値が読み込まれています。
let a = "Yo"
// "Yo"自体(値)がコピーされます
let b = a
// bの向き先(値)が変わります。
b = "Taka"

image.png

再代入

constを使う場合、もちろん再代入ができません。
つまり、constを定義した場合は、変数 aの向き先を変更できなくなるのです。

const a = "Yo"
a = "Taks"

オブジェクト

ミュータブルで、参照を名前付きで管理している入れ物です。
この時のミュータブルの意味は、"Yo"の値が変わったとしても、propへの参照が変わらないことから、ミュータブルと呼ばれます。

let a = {
  prop: "Yo";
}

image.png

コピー

下記図の通り、オブジェクトへの参照がコピーされることになります。(背景色が異なっているところ)
{ prop } がみている値が変更されるので、元の変数の値も変更されることになります。

let a = {
  prop: "Yo"
};

let b = a;

b.prop = "Taka";

image.png

再代入

オブジェクトの再代入はできないが、オブジェクト内のプロパティは再代入できます。

比較

オブジェクトのプロパティを比較する必要があり、オブジェクトの比較をしても、参照を比較することになるので、期待する結果とはなりません。

0
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
0
1