JS method proxy and js proxy
Author: Jiang, Jilin
As a scripting language, JS is very easy to use. With its flexibility, you can easily expand functions. Today, let's talk about the JS method proxy. Method proxy is a common method extension form in script language. This flexible form has the advantage that it can be easily extracted and modified when complicated JS code needs to be extended. However, its shortcomings are also very obvious, which may cause code fragmentation and thus is a double-edged sword.
Basic Form
Var _ func = obj. func; Obj. func = function (){ Return _ func (); }; |
Here, the func method of obj is the original method. We use a _ func variable to save this method, and then override the func method to return the original method called. Very easy to understand.
Variable Length Parameter
Sometimes, we may encounter the form of an indefinite parameter. We can make the following changes:
Var _ func = obj. func; Obj. func = function (){ Return _ func. apply (this, arguments ); }; |
Here, the JS method proxy has been written in two forms. At this time, you may wonder how this method proxy works? Let's take a look at several examples:
Override static methods
For some reason, we need to transmit the printed data to the specified server while printing on the console. In the development process, the original console. log method is directly used for output. Then, we can make the following changes.
First, build the proxy method:
Var _ log = console. log; Console. log = function (){ Return _ log. apply (this, arguments ); }; |
Then, insert the ajax call logic:
Console. log = function (){ Var _ args = Array. prototype. slice. call (arguments ); $. Post ("srvAddr", {userID: userID, args: _ args }); Return _ log. apply (this, arguments ); }; |
It is easy to predict the effect:
Prototype proxy
Sometimes, we need to take over the method of a class directly. Then, we need to proxy the methods in prototype. Now let's assume that Array supports numerical sorting by default:
Var _ sort = Array. prototype. sort; Array. prototype. sort = function (){ _ Sort. apply (this, arguments ); }; |
We first check whether the elements in the array are numbers. If yes, they are sorted by numbers. Otherwise, they are sorted by default:
Var _ sort = Array. prototype. sort; Array. prototype. sort = function (){ Var _ isNum = true; For (var I = 0; I <this. length; I + = 1 ){ If (typeof this [I]! = "Number "){ _ IsNum = false; Break; } } If (_ isNum ){ Return _ sort. call (this, function (a, B ){ Return a-B; }); } Else { Return _ sort. apply (this, arguments ); } }; |
Original sorting method (convert numbers into character sorting)
Sort by proxy
Note:Here is only an example of Prototype Method proxy. In actual development, try to avoid proxy for native object prototype methods.
Heavy Load
In jQuery, the toggle method has multiple reloads, one of which is toggle (display). By accepting the boolean parameter, you can determine whether the element is displayed or hidden. The fadeToggle method does not accept this parameter. Let's perform a simple proxy to make it support the boolean parameter:
Var _ fadeToggle = $. fn. fadeToggle; $. Fn. fadeToggle = function (display ){ If (arguments. length ===1 & typeof display === "boolean "){ If (display ){ Return this. fadeIn (); } Else { Return this. fadeOut (); } } Return _ fadeToggle. apply (this, arguments ); }; |
Determine whether to call the fadeIn or fadeOut Method Based on the parameter length and the type of the received parameter. If not, the original fadeToggle method is called. Similarly, slideToggle can also be used.
* Inheritance
Inheritance, we sometimes need to call the parent class method for implementation. This is similar to super in java. A simple example. We have defined a Person, which can be laugh. Define a Robot inheritance at the same time, which is the laugh of the Person, but is slightly modified:
Var Person = function (){ This. name = ""; This. laugh = function (){ Return "Ha ha! "; }; Return this; }; Var Robot = function (){ Person. apply (this ); Var _ laugh = this. laugh; This. laugh = function (){ Return encodeURIComponent (_ laugh ()); }; Return this; }; |
Hijacking
When it comes to hijacking, it is linked to security. Today, most websites are used to developing with open source js libraries, but if malicious code is inserted, therefore, security becomes insecure (for example, a large number of unverified browser plug-ins in chrome ). Here are some examples of hijacking.
Ajax hijacking
Many people think that important user parameters are stored in the scope (for example, dynamically generated secureID) through closures, so even malicious code inserted cannot be obtained, it seems sufficient to forge ajax requests to obtain important information. But what if the entire ajax request is intercepted?
Var _ ajax = $. ajax; $. Ajax = function (){ Var $ p = _ ajax. apply ($, arguments ); $ P. done (function (data ){ // Do something... }); Return $ p; }; |
All ajax requests (get, post, and getJSON) in jQuery will eventually be implemented by calling $. ajax. The method proxy directly hijacks the $. ajax method and returns a normal promise object, which makes page script running unaffected. But the data has actually been hijacked.
Array hijacking
Array has many prototype methods, such as push, pop, shift, and unshift. We only need a simple proxy Array Operation Method to intercept data.
Var _ push = Array. prototype. push; Array. prototype. push = function (){ // Do something... Return _ push. apply (this, arguments ); }; |
Okay. The above is the method proxy introduction. The method proxy will confuse the code logic, making the code structure hard to understand. In the daily development process, we should try to avoid using it. It is used only when the proxy is overloaded, or when you change some logic of the obscure legacy code. In this way, you can avoid hurting yourself by mistake.