雖然 Java 與 JavaScript 名稱相似,但在 Java 應用中整合 JavaScript(如腳本引擎、前端互動、Node.js 整合)時,掌握 JS 進階特性至關重要。本文系統整理物件建構、原型繼承、遞迴、作用域、資料傳遞等核心概念。
// 內建建構函數
var obj = new Object(); // 空物件
var date = new Date(2024, 0, 1); // 日期物件(月份 0 基底)
// 自訂建構函數
function Circle(x, y, radius) {
this.x = x; // 圓心 X
this.y = y; // 圓心 Y
this.r = radius; // 半徑
}
var myCircle = new Circle(10, 20, 5); // 實例化
// 定義共享屬性
Circle.prototype.PI = Math.PI;
// 定義共享方法
Circle.prototype.area = function() {
return this.PI * this.r * this.r;
};
var c1 = new Circle(0, 0, 10);
var c2 = new Circle(5, 5, 20);
console.log(c1.area()); // 314.159...
console.log(c2.area()); // 1256.637...
// 動態擴充內建類型
String.prototype.trim = function() {
return this.replace(/^\s+|\s+$/g, '');
};
var str = " Hello World ";
console.log(str.trim()); // "Hello World"
遞迴讓函數呼叫自身解決問題,需包含基礎案例與遞迴步驟,避免無限遞迴導致堆疊溢位。
// 階乘計算 - 經典遞迴範例
function factorial(n) {
n = Math.floor(n); // 確保整數
if (n < 0) return -1; // 基礎案例:拒絕負數
if (n === 0) return 1; // 基礎案例:0! = 1
return n * factorial(n - 1); // 遞迴步驟
}
console.log(factorial(5)); // 120
// 防護性遞迴:限制深度
function safeFactorial(n, depth = 0) {
if (depth > 1000) throw new Error("遞迴深度超限");
n = Math.floor(n);
if (n < 0) return -1;
if (n === 0) return 1;
return n * safeFactorial(n - 1, depth + 1);
}
JavaScript 僅有全域作用域與函數作用域(ES6 前無區塊作用域),變數提升特性需特別注意。
var globalVar = "全域";
function scopeDemo() {
var localVar = "區域";
console.log(globalVar); // 可存取全域
console.log(localVar); // 可存取區域
// 變數提升範例
console.log(hoisted); // undefined(非 ReferenceError)
var hoisted = "已提升";
// 同名變數遮蔽
var globalVar = "區域同名";
console.log(globalVar); // "區域同名"
}
scopeDemo();
console.log(globalVar); // "全域"(未被修改)
| 類型 | 分類 | 複製/傳遞 | 比較 | 範例 |
|---|---|---|---|---|
| Primitive | Number, Boolean, null, undefined | 傳值(獨立副本) | 按值比較 | 42, true, null |
| String | 不可變基本型別 | 傳參考,但行為如傳值 | 按值比較 | "hello", 'world' |
| Object | Object, Array, Function, Date, RegExp | 傳參考(共享同一實體) | 按參考比較 | {}, [], function(){} |
// 物件傳參考示例
function modify(obj) {
obj.name = "已修改"; // 影響原物件
obj = { name: "新物件" }; // 重新指向區域參數,不影響外部
}
var original = { name: "原始" };
modify(original);
console.log(original.name); // "已修改"
// 陣列傳參考
function pushItem(arr) {
arr.push(99); // 影響原陣列
arr = [1,2,3]; // 重新指向,不影響外部
}
var nums = [1,2,3];
pushItem(nums);
console.log(nums); // [1, 2, 3, 99]
// 破壞性修改:重新指派參數,外部不可見
function clobber(param) {
param = new Object(); // 區域重新指派
param.msg = "無效";
}
// 非破壞性修改:修改物件屬性,外部可見
function update(param) {
param.msg = "已更新"; // 修改共享物件屬性
}
var obj = { msg: "原始" };
clobber(obj);
console.log(obj.msg); // "原始"
update(obj);
console.log(obj.msg); // "已更新"
=== 嚴格比較=== 比較內容,大小寫敏感=== 僅比較參考是否指向同一實體JSON.stringify()、Lodash _.isEqual() 或自訂遞迴比較date.getTime() 比較數值現代 JavaScript 引入 let/const(區塊作用域)、箭頭函數、類別語法、解構賦值、模組系統、Promise/async-await 等特性,大幅改善上述傳統模式的限制。在 Java 整合 GraalJS、Nashorn 或前端 TypeScript 專案中,建議優先採用現代語法。