JavaScript Tips

許聖泉 Michael Hsu
5 min readNov 19, 2020

--

這個系列會把每天讀到、看到、想到、聽到、夢到關於 JavaScript 的技巧記錄下來,所以會比較零碎...maybe 等過了幾天後,會針對各主題整理出完整文章

Photo by Daniel Seßler on Unsplash

Primitive Types and Object Types

基本型別(Primitive Types)

  • number
  • string
  • boolean
  • null
  • undefined
  • symbol

物件型別(Object Types)

  • array
  • function
  • date
  • map

一般來說,基本型別(Primitive Types)會是 call by value,而物件型別(Object Types)則是 call by reference。

Call by value

var x = "foo";
var y = "bar";
var a = x;
var b = y;
a = 123;
b = "xyz";
console.log(x, y, a, b) // foo bar 123 xyz

當 var a = x 時,實際上是把 x 的值複製給了 a,所以其實 a 和 x 都是獨立的不互相影響。

Call by reference

var foo = [1];
var bar = foo;
foo.push(2);
console.log(foo, bar); // [1, 2] [1, 2]

當 foo 被宣告時,會在記憶體的某處建立一個物件,並將 foo 指向這個物件。接著 var bar = foo 的時候,就是讓 foo 把相同的指向再傳給 bar。 此時兩個變數都是指向同個物件了,因此對這個物件的所有操作,都會同時影響到 foo 和 bar。

再看一題

function foo(bar) {
this.a = bar;
this.b = new Array(bar[0], bar[1], bar[2]);
}
const bar = [10, 10, 10];
const zzz = new foo(bar);
bar[0] = 100;
bar[3] = 100;
console.log(bar[0] + zzz.a[3] + zzz.b[0]); // 210

typeof

typeof null; // 'object'
typeof undefined; // 'undefined'
typeof function() {}; // 'function'
typeof [1, 2, 3]; // 'object'
typeof NaN; // 'number'

除了平常常看到型態以外,以上這幾種結果需要特別注意

Scope

指的是當前的執行上下文。值和表達式在其中 “可見” 或可被訪問到的上下文。

如果一個變數或者其他表達式不 “在當前的作用域中”,那麼它就是不可被使用的。

作用域也可以根據程式碼層次分層,以便子作用域可以訪問父作用域,通常是指沿著鍊式的作用域鏈查找,而不能從父作用域引用子作用域中的變數和引用。

當然,一個 Function 將生成一個閉包(通常是返回一個函數引用),這個函數引用從外部作用域(在當前環境下)可以訪問閉包內部的作用域。例如,下面的代碼是無效的,並不是閉包的形式):

function foo() {
var x = "hello world"; // x 只能在 foo 函数中使用
console.log(x);
}

console.log(x); // error

但是,由於變數在函數外被聲明為全局變數,因此下面的代碼是有效的(當前作用域不存在的變數和引用,就沿著作用域鏈繼續尋找):

var x = "hello world";

foo();

function foo() {
console.log("Inside function");
console.log(x);
}

console.log("Outside function");
console.log(x);

Hoisting(拉升)

編譯器會由上到下逐行將程式碼轉為電腦可懂的命令,在這個編譯的階段,編譯器找出所有的變數並繫結所屬範疇,但不賦值,所以此刻變數所帶的值是 undefined;而在執行階段,JavaScript 引擎才會處理給值的事情。

JavaScript 在執行任何程式碼前,會將函數宣告放入記憶體中的優點之一是,你可以在宣告一個函數之前使用該函數。例如:

var foo;

console.log(foo); // undefined
foo = 2;

JavaScript 只會拉升宣告,不會拉升其初始化。如果一個變數先被使用再被宣告和賦值的話,使用時的值是 undefined。如果你先賦值、再使用、最後宣告該變數,使用時能獲取到所賦的值

foo = 2;console.log(foo); // 2var foo;

即刻調用函式運算式(Immediately Invoked Function Expression, IIFE)

IIFE 是一個在定義時就會立即執行的 JavaScript 函數。使用 IIFE 的好處主要是不污染全域範疇。

(function () { 
var name = "foo";
})();

name // error

--

--

許聖泉 Michael Hsu
許聖泉 Michael Hsu

No responses yet