6. Node.js REPL 環境

本教材撰寫於 Node.js 版本:v8.9.1

6.1 REPL 環境

$ node
> 1+1
2
>

_

> 1 + 1
2
> _ + 1
3

##回傳

> x = 1
1
> var x = 1

6.2理解 “not defined” / “undefined” / “null”

// undefined

var x x undefined

// null

var y = null y null ```

6.2.1 使用 typeof 檢查型別

typeof 運算子會傳回一個字串值, 指出未經運算 (unevaluated) 的運算元所代表的型別。

// Numbers
typeof 37 === 'number';
typeof 3.14 === 'number';
typeof Math.LN2 === 'number';
typeof Infinity === 'number';
typeof NaN === 'number'; // 雖然是 "Not-A-Number"
typeof Number(1) === 'number'; // 但是不要使用這種方式!

// Strings
typeof "" === 'string';
typeof "bla" === 'string';
typeof (typeof 1) === 'string'; // typeof 一律會傳回一個字串
typeof String("abc") === 'string'; // 但是不要使用這種方式!

// Booleans
typeof true === 'boolean';
typeof false === 'boolean';
typeof Boolean(true) === 'boolean'; // 但是不要使用這種方式!

// Undefined
typeof undefined === 'undefined';
typeof blabla === 'undefined'; // 一個 undefined 變數

// Objects
typeof {a:1} === 'object';
typeof [1, 2, 4] === 'object'; // 請使用 Array.isArray 或者 Object.prototype.toString.call 以區分正規運算式和陣列
typeof new Date() === 'object';

// 注意!
typeof null === 'object';

// 不要這樣用!
typeof new Boolean(true) === 'object'; // 這樣會令人混淆。不要這樣用!
typeof new Number(1) === 'object'; // 這樣會令人混淆。不要這樣用!
typeof new String("abc") === 'object';  // 這樣會令人混淆。不要這樣用!

// Functions
typeof function(){} === 'function';
typeof Math.sin === 'function';

練習

嘗試輸入以下程式碼並觀察其結果,

var a = 1;
var b = 1.123;
var c = 'abc';
var d = {};
var e = [];
var f = function () {};

typeof a
typeof b
typeof c
typeof d
typeof e
typeof f

6.2.2 問題

var a = 1, b, c = null;
b = c;
c = a;
a = 2;
console.log('typeof b=>', typeof b);

6.2.3 參考連結

6.3 全域變數

// 在瀏覽器
var a = 1;
window.a => 1;

// 在 Node
var x = 1;
global.x => undefined;
console.log(123);

console.info(123);

console.warn(123);

console.time('tag');

console.timeEnd('tag');

6.4 全域函式

6.5 callback

Node 使用 JavaScript 作為開發語言,其特色就是單執行緒,一次只能執行一個任務,所以會使用非同步執行(asynchronous opertion)的方式來達成多個任務的協調。也就是說,每個任務不會是立刻執行,而是輪到前面的處理佇列完成後才執行。

通常 JavaScript 程式都會使用 callback 方式來實作需要等待的任務,如下範例:

var callback = function (error, value) {
  if (error) {
    return console.log(error);
  }
  console.log(value);
}

var isTrue = function(value, callback) {
  if (value === true) {
    callback(null, "Value was true.");
  }
  else {
    callback(new Error("Value is not true!"));
  }
}

6.6 callback 與 try-catch

try {
  db.User.get(userId, function(err, user) {
    if(err) {
      throw err
    }
    // ...
  })
} catch(e) {
  console.log(Oh no!);
}

6.7 錯誤處理

function (err, data) {
  if (err) {
    if (!err.noPermission) {
      return next(err);
    }
  }
}

6.8 執行 .js 檔案

下載 app.js

$ node app.js

6.9 練習

6.10 提升

執行環境 (execution content)

範例一

// 這是比較好的做法,不依賴 hoisting
var a = 'Hello World';
console.log(a);

function b() {
  console.log('呼叫 b');
}
b();

範例二

console.log(a); // ?
b();

var a = 'Hello World';

function b() {
  console.log('呼叫 b');  // ?
}

範例三

console.log(a); // ?
console.log(b); // ?
b();  // ?

var a = 'Hello World';

var b = function() {
  console.log('呼叫 b');
}

6.9 範圍

var value = 1;
value = 1;

使用情境

重點提醒

盡量減少使用全域變數,因為如果你使用很多 Javascript 函式庫,免不了使用到同樣名字的全域變數,將導致不可預期的副作用。 對類別語言而言 scope 是什麼?

對 Javascript 而言 scope 是什麼?

範例一

var message = 'hi';

if(true){
  var message = 'bye';
  console.log('=== 1 ===');
  console.log(message); // ?
}

console.log('=== 2 ===');
console.log(message); // ?

範例二

var message = 'hi';

function greet() {
  var message = 'bye';
  console.log(message);   // ?
}

console.log('=== 1 ===');
console.log(message); // ?
console.log('=== 2 ===');
greet();
console.log('=== 3 ===');
console.log(message); // ?

範例三:忽略 var 的情況

message = 'hi';

function greet() {
  message = 'bye';
  console.log(message);
}

console.log('=== 1 ===');
console.log(message);
console.log('=== 2 ===');
greet();
console.log('=== 3 ===');
console.log(message);

範例 4

function test(){
  var a = 10
}

if(true){
  var b = 20
}

console.log(a) // a is not defined 存取不到
console.log(b) // 存取得到

6.10 const/let

範例1

var a = 1;
let b = 1;

function func1() {
  a = 2;
  b = 2;
  c = 2;
  console.log('a@func1', a);
  console.log('b@func1', b);
}
func1();

範例2

const c = 1;

function func2() {
  c = 2;
  console.log('c@func2', c);
}
func2();

範例3

function func3() {
  var d = 3;
  let e = 3;
  const f = 3;
  console.log('d@func3=>', d);
  console.log('e@func3=>', e);
  console.log('f@func3=>', f);
}
func3();

console.log('d=>', d);
console.log('e=>', e);
console.log('f=>', f);

範例4

function test() {
  let a = 10
}

if (true) {
  const b = 20
}

console.log(a) // a is not defined 存取不到
console.log(b) // b is not defined 存取不到

範例5: array/object

const a = 10
a = 20  // TypeError: Assignment to constant variable. 錯誤

const a = []
a[0] = 1

const b = {}
b.foo = 123

範例 6:let in for

for (let i = 0; i < 10; i++) {
  console.log('in for statement: i', i)
}

console.log(i) // ReferenceError: i is not defined(…) 存取不到

建議

接下來…