What is function hijacking? In fact, it is to call the function to add a layer of wrapper function, in the wrapper function to call the original function, a bit like the role of the proxy server, intercept some global objects and methods, can achieve some very convenient global function, today I will throw out a brick to introduce a piece of information to share with you.

Life is too short to console.log

Some time ago, I saw the animation application of emoji ICONS in the address bar, which was quite interesting and entertaining. I tried to apply emoji to the example of function hijacking that I was studying, and the actual effect was quite good. I amused myself and shared it with everyone, adding a bright color to the dull development life.

Console. log itself supports sample format. The first parameter is formatted with %c, and the second parameter can be passed to the style sheet to achieve gradient color, display images, and other very nice effects. If console.log can change color by default, we will try to hijack console.log to add a default function, make it randomly change color and icon output each time, to protect eyesight, increase the font size, effect is as follows:

var _consoleLog=window.console.log;
window.console.log=function (){
    if(arguments.length==1 && typeof arguments[0]! ="object") {var iconList=["🌏"."🌛"."🌟"."🔥"."🐦"."👿"."🎃"."🎊"."🎋"."🎁"."🍀"."🌷"."🌱"."🍁"."🌸"."🍃"."🌿"."🍒"."🍎"."🍊"."🍓"."🍍"."🍇"]
        var colorList=["background-color:#8BC34A; color:white"."background-color:#42b983; color:white"."background-color:#33A5FF; color:white"."background-color:orange; color:white"."background-color:#2EAFB0; color:white"."background-color:#6EC1C2; color:white"."background-color:#FFDD4D; color:black"."background-color:#7F2B82; color:white"."background-color:#4b4b4b; color:white"."background-color:#E41A6A; color:white"]
        var idx1=Math.floor(Math.random()*iconList.length);
        var idx2=Math.floor(Math.random()*colorList.length);
        var msg=arguments[0];
        msg="%c "+iconList[idx1]+""+msg;
        
        _consoleLog(msg,"font-size:20pt;"+colorList[idx2])
    }else{
        _consoleLog.apply(this.arguments)}}console.log("hello,world")
Copy the code

Introduce it in the public code, and you’ll see colorful console output every day. Note: Windows 7 and below do not support emoji colors

Method to prevent dizziness: Automatic formatting of JSON output

Json. stringify takes 3 arguments. The third argument can specify a blank string for indentation, which is used to beautify the output (pretty-print). If the argument is a number, it represents how many Spaces there are; The upper limit is 10. If the value is less than 1, there are no Spaces. If the argument is a string (the first ten letters of the string), the string is used as a space; The second argument is a callback function that can be used to filter each attribute value, usually without passing NULL,

JSON.stringify({result:{a:1,b:2}},null,4)
Copy the code

The output is already formatted JSON, perfect:

{
    "result": {
        "a": 1,
        "b": 2}}Copy the code

Function hijacking is the default method for passing three arguments to each call:

var _stringify=JSON.stringify
JSON.stringify=function (){
    if(arguments.length==1) {return _stringify(arguments[0].null.4)}else{
    	return _stringify.apply(this.arguments)}}Copy the code

Try json.stringify again and format the output without passing 3 parameters. Be careful not to perform function hijacking repeatedly, as this will create a recursive loop. Call the toString method of a function. If it is a native function, it will return [native code] as follows

"function stringify() { [native code] }"
Copy the code

Do a character check.

Be prepared for a rainy day

Some novices like to debug with alert. This kind of code is a disaster if it goes online. Let’s write a hijacking and put an end to this problem forever:

window.alert=function (){
console.log(arguments[0])}Copy the code

No longer play out of alert, you ok……..

Real black tech # 1: Mock. js intercepts Ajax requests without being fooled

Mock data is inevitable in the process of separating the front end from the back end, and there are two common solutions.

  1. Client-side mocks, which have the advantage of intercepting requests at the front end without having to build a server.
  2. A server-side mock is a null interface that returns dead data. An HTTP interaction flow that is close to the real world.

I implemented a similar feature in MockJs years ago and then found out there was an open source project. XMLHttpRequest is a function hijacking of the window.XMLHttpRequest object. It is a function hijacking of the send method and the onreadyStatechange event. XHR does not use addEventListener to listen for events. Instead, it uses Dom level 0 to add a callback to the on event name. Otherwise, we would need to hijack addEventListener. We could make a mess if we’re not careful.

The hijacking of an object attribute is of course to rewrite the onReadyStatechange callback using defineProperty. If the mock matches the URL, it returns dummy data, and if it doesn’t match it doesn’t affect any other normal Ajax interface, triggering the original XHR process. Below is the complete working code. For the sake of demonstration, I have omitted the fixed addresses for several infrequently used attributes and the re matching URL rule library.

var __XMLHttpRequest=XMLHttpRequest;
window.XMLHttpRequest=function (){
       var resultObj={
           xhr:new __XMLHttpRequest(),
           onreadystatechange:null.open:function (method,url,async){
               this.url=url;
               this.method=method;
           },
           send:function (data){
               // Change the sequence asynchronously so that send is executed after onreadyStatechange
               setTimeout((a)= > {
                   if(this.url.indexOf("http://www.baidu.com/post") > =0) {// Match the url rule, this is business code omitted, first use the fixed address
                       this.readyState=4;
                       this.status=200;
                       this.responseText="{result:'hello,baidu'}"; // Write dead message first for demonstration
                       this.onreadystatechange({mock:true});
                   }else{
                       this.xhr.open(this.method,this.url);
                       this.xhr.send(data); }},0); }}Object.defineProperty(resultObj,"onreadystatechange", {
           get:function (){
               return this.xhr.onreadystatechange;
           },
           set:function (func){
               this.xhr.onreadystatechange= (arg) = >{
                   if(arg.mock){ // The mock interface directly triggers the callback
                       func();
                   }else{ // If no match is found, copy back the original XHR data
                       this.readyState=this.xhr.readyState;
                       this.status=this.xhr.status;
                       this.responseText=this.xhr.responseText; func(); }}; }})return resultObj;
}
Copy the code

We write a use case to run once, note: in order to simplify the code, match the url above to write dead, can only use this address at http://www.baidu.com/post

var xhr=new XMLHttpRequest()
xhr.open("post"."http://www.baidu.com/post");
xhr.send();
xhr.onreadystatechange=function (){
    console.log(xhr.responseText)
}
Copy the code

{result:’hello,baidu’} {result:’hello,baidu’}}

The real Black tech 2: non-intrusive interface layer exception monitoring, elegant way to blame the problem on the backend

Many years ago, users often appear some problems, the development is difficult to reproduce, the background students nerve is bigger, not afraid not afraid, not a journal, often do not check or call logs, front end and no log, finally basic it is front back responsibility, then we front-end team is realized in the XHR layer packaging a monitor backend interface anomaly and timeout phenomenon, Elegant cast boiler to the background, save a lot of time (in fact, a lot of server problems or network reasons, the background really can not check out). Many years later, after I realized the mock, I realized that directly hijacking XHR is a better solution, which can be applied to all projects. Last year, I saw a company make it: www.fundebug.com, I was very pleased, many ideas coincide with me. In fact, such a solution is difficult to productize, and there is a huge gap between a technology and productization.

Let’s talk about the core principles

  • On the Node. js side, there is uncaughtException, which can catch the type of exception and error stack information. Technology is really changing with each passing day. The exception stack can only be retrieved by tracting arguments. Callee. caller up the stack function to toString.

  • If a mock does not match a normal Ajax request, check the status code and the message directly in readyStatechange. If a status code exception is found, it will be reported. If your background error message still returns 200 status code, you can only formulate packet specifications and specify the return value of success. If the key word of success cannot be detected, the message is processed as failure and logs are reported.

  • For timeout detection of an interface, you can add a setTimeout to send. If onReadyStatechange is not triggered by the specified time, the timeout log is reported.

In fact, it is based on the above mock. Js, add a few lines of code to implement, not detailed code, roughly the code is as follows:

this.xhr.onreadystatechange= (arg)=>{
    if(arg. Mock){// Mock interface, which directly triggers the callback func(); }else{// If no match is found, copy back the original XHR dataif(this.readyState==4 && this.status! =200){reportError() // Report logs} //....... Omit}};Copy the code

conclusion

Mastered the function hijacked, we will be a weapon, more ammunition bunker technology will never be cold, it can realize a lot of application, to give full play to your imagination, as a research and development, it is very important to keep the curiosity, if found a black function of science and technology, are you still don’t know how he, he must go to study the principle of Then think about where else you can apply it, and you’ll really have the technology.

Finally, here are my daily recommendations for open source projects:

Webcontext, the simplest Node. js web development framework, github address: github.com/windyfancy/…