Để xác định hàm nào đang gọi hàm hiện tại (caller function) trong JavaScript, cách truyền thống là sử dụng thuộc tính arguments.callee.caller hoặc functionName.caller. Tuy nhiên, đây là tính năng phi chuẩn (non-standard), deprecated (lỗi thời), và bị cấm trong Strict Mode.
⚠️ CẢNH BÁO QUAN TRỌNG
- Không dùng trong production code. Không thuộc chuẩn ECMAScript.
- Bị loại bỏ trong Strict Mode (
"use strict";) - némTypeError. - Hiệu năng kém (ngăn chặn tối ưu hóa JIT).
- Không hoạt động với Arrow Function, Class Method, Async Function.
Cách cũ (Chỉ để hiểu legacy code)
function display() {
// Cách 1: arguments.callee.caller (Deprecated)
// console.log("Caller (arguments):", arguments.callee.caller);
// Cách 2: functionName.caller (Deprecated)
console.log("Caller (name.caller):", display.caller);
}
function callerFunc() {
display();
}
callerFunc(); // Log: function callerFunc() { display(); }
✅ CÁCH HIỆN ĐẠI, AN TOÀN, CHUẨN (Best Practices)
1. Truyền context/function reference như tham số (Explicit)
function processData(data, onComplete) {
// Xử lý...
onComplete(result); // Gọi callback rõ ràng
}
function handleResult(result) {
console.log("Xử lý xong:", result);
}
processData(myData, handleResult); // Rõ ràng ai gọi ai
2. Dùng Error Stack Trace (Debug/Logging)
function getCallerInfo() {
const stack = new Error().stack;
// Parse stack trace để lấy tên hàm gọi
// Format khác nhau giữa browser/Node.js
return stack;
}
function myFunc() {
console.log(getCallerInfo());
}
function caller() { myFunc(); }
caller();
3. Sử dụng Console.trace() (Debug trong DevTools)
function targetFunc() {
console.trace("Đang ở targetFunc, stack trace:");
}
function caller() { targetFunc(); }
caller();
Xem trong Console DevTools: hiển thị đầy đủ call stack có link nhảy đến source.
4. Wrapper/Decorator (AOP - Aspect Oriented Programming)
function withLogging(fn) {
return function(...args) {
console.log(`Gọi ${fn.name} từ`, new Error().stack.split("\n")[2].trim());
return fn.apply(this, args);
};
}
const loggedFunc = withLogging(function myFunc() { ... });
5. Async/Await + Error Stack (Node.js/Modern Browser)
async function asyncCaller() {
await asyncTarget();
}
async function asyncTarget() {
// Lấy stack trace async
const stack = new Error().stack;
console.log(stack);
}
So sánh
| Cách | Chuẩn? | Strict Mode? | Hiệu năng | Độ tin cậy | Dùng cho |
|---|---|---|---|---|---|
func.caller | ❌ Không | ❌ Lỗi | Kém | Thấp | Legacy code only |
| Truyền callback/context | ✅ Có | ✅ OK | Tốt | Cao | Production (Khuyên dùng) |
Error().stack | ⚠️ Non-standard nhưng phổ biến | ✅ OK | Trung bình | Trung bình (parse phức tạp) | Debug, Logging, Monitoring |
console.trace() | ✅ Console API | ✅ OK | Tốt (DevTools) | Cao | Debug thủ công |
Kết luận: Đừng dùng function.caller hay arguments.callee.caller. Hãy thiết kế code rõ ràng: truyền callback, dùng Promise/async-await, hoặc dùng console.trace()/Error().stack cho mục đích debug/logging.