Tự động thêm console.log vào mọi chức năng


97

Có cách nào để thực hiện bất kỳ hàm nào xuất ra một câu lệnh console.log khi nó được gọi bằng cách đăng ký một hook chung ở đâu đó (nghĩa là, không sửa đổi chính hàm thực tế) hoặc thông qua một số phương tiện khác không?


câu hỏi tuyệt vời, tôi rất muốn biết liệu điều này có khả thi không nhưng tôi khá chắc chắn là không ... Có thể thêm yêu cầu tính năng để nó được thêm vào công cụ js cho trình duyệt yêu thích của bạn? :-)
Endophage

Perfect câu hỏi, tôi cần một cái gì đó tương tự như thế này
mjimcua

Câu trả lời:


62

Đây là một cách để tăng cường tất cả các chức năng trong không gian tên chung với chức năng bạn chọn:

function augment(withFn) {
    var name, fn;
    for (name in window) {
        fn = window[name];
        if (typeof fn === 'function') {
            window[name] = (function(name, fn) {
                var args = arguments;
                return function() {
                    withFn.apply(this, args);
                    return fn.apply(this, arguments);

                }
            })(name, fn);
        }
    }
}

augment(function(name, fn) {
    console.log("calling " + name);
});

Một mặt trái là không có hàm nào được tạo sau khi gọi augmentsẽ có hành vi bổ sung.


Nó có xử lý các giá trị trả về của hàm đúng cách không?
SunnyShah

2
@SunnyShah Không nó không: jsfiddle.net/Shawn/WnJQ5 Nhưng có một điều này: jsfiddle.net/Shawn/WnJQ5/1 mặc dù tôi không chắc chắn nó sẽ làm việc trong các trường hợp TẤT CẢ ... Sự khác biệt là thay đổi fn.apply(this, arguments);đểreturn fn.apply(this, arguments);
Shawn,

2
@Shawn @SunnyShah Đã sửa. Chỉ cần thêm a returnvào hàm trong cùng.
Wayne

làm việc gần như tốt nhưng tôi nhận được một lỗi với jquery này: gọi: if (jQuery.isFunction (lSrc)) và nó nói: Lỗi Loại: jQuery.isFunction không phải là một chức năng
fekiri Malek

4
Giải pháp này không sử dụng jQuery
Wayne

8

Đối với tôi, đây có vẻ là giải pháp thanh lịch nhất:

(function() {
    var call = Function.prototype.call;
    Function.prototype.call = function() {
        console.log(this, arguments); // Here you can do whatever actions you want
        return call.apply(this, arguments);
    };
}());

7

Phương thức Proxy để ghi lại các cuộc gọi Hàm

Có một cách mới sử dụng Proxy để đạt được chức năng này trong JS. giả sử rằng chúng ta muốn có một console.logbất cứ khi nào một hàm của một lớp cụ thể được gọi:

class TestClass {
  a() {
    this.aa = 1;
  }
  b() {
    this.bb = 1;
  }
}

const foo = new TestClass()
foo.a() // nothing get logged

chúng ta có thể thay thế việc khởi tạo lớp của chúng ta bằng một Proxy ghi đè từng thuộc tính của lớp này. vì thế:

class TestClass {
  a() {
    this.aa = 1;
  }
  b() {
    this.bb = 1;
  }
}


const logger = className => {
  return new Proxy(new className(), {
    get: function(target, name, receiver) {
      if (!target.hasOwnProperty(name)) {
        if (typeof target[name] === "function") {
          console.log(
            "Calling Method : ",
            name,
            "|| on : ",
            target.constructor.name
          );
        }
        return new Proxy(target[name], this);
      }
      return Reflect.get(target, name, receiver);
    }
  });
};



const instance = logger(TestClass)

instance.a() // output: "Calling Method : a || on : TestClass"

kiểm tra xem điều này có thực sự hoạt động trong Codepen không


Hãy nhớ rằng việc sử dụng Proxymang lại cho bạn nhiều chức năng hơn là chỉ ghi lại tên bảng điều khiển.

Ngoài ra phương pháp này hoạt động trong Node.js quá.


Bạn cũng có thể làm điều này mà không cần sử dụng các phiên bản và lớp học? Nói cụ thể trong node.js?
Revadike

@Revadike điều này sẽ hữu ích: stackoverflow.com/a/28708700/5284370
Soorena

1

Nếu bạn muốn ghi nhật ký được nhắm mục tiêu hơn, đoạn mã sau sẽ ghi nhật ký các lệnh gọi hàm cho một đối tượng cụ thể. Bạn thậm chí có thể sửa đổi nguyên mẫu Đối tượng để tất cả các phiên bản mới cũng có thể ghi nhật ký. Tôi đã sử dụng Object.getOwnPropertyNames thay vì for ... in, vì vậy nó hoạt động với các lớp ECMAScript 6, không có các phương thức có thể liệt kê.

function inject(obj, beforeFn) {
    for (let propName of Object.getOwnPropertyNames(obj)) {
        let prop = obj[propName];
        if (Object.prototype.toString.call(prop) === '[object Function]') {
            obj[propName] = (function(fnName) {
                return function() {
                    beforeFn.call(this, fnName, arguments);
                    return prop.apply(this, arguments);
                }
            })(propName);
        }
    }
}

function logFnCall(name, args) {
    let s = name + '(';
    for (let i = 0; i < args.length; i++) {
        if (i > 0)
            s += ', ';
        s += String(args[i]);
    }
    s += ')';
    console.log(s);
}

inject(Foo.prototype, logFnCall);

-1

Đây là một số Javascript thay thế thêm console.log vào mọi hàm trong Javascript; Chơi với nó trên Regex101 :

$re = "/function (.+)\\(.*\\)\\s*\\{/m"; 
$str = "function example(){}"; 
$subst = "$& console.log(\"$1()\");"; 
$result = preg_replace($re, $subst, $str);

Đó là một 'hack nhanh chóng và bẩn thỉu' nhưng tôi thấy nó hữu ích cho việc gỡ lỗi. Nếu bạn có nhiều chức năng, hãy cẩn thận vì điều này sẽ thêm rất nhiều mã. Ngoài ra, RegEx đơn giản và có thể không hoạt động đối với các tên / khai báo hàm phức tạp hơn.


-10

Bạn thực sự có thể đính kèm chức năng của riêng mình vào console.log cho mọi thứ tải.

console.log = function(msg) {
    // Add whatever you want here
    alert(msg); 
}

2
chính xác hay không, nó không trả lời câu hỏi. ở tất cả. (bất cứ ai trong trường hợp vẫn còn nhầm lẫn)
redfox05
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.