This object is an extension of function. The most important one is the bind method. The help document of prototype specifically says: Prototype takes issue with only one aspect of functions: binding. The wrap method is also very important. In class inheritance The mechanism uses the wrap method to call the method of the same name of the parent class. argumentNames bind bindAsEventListener curry defer delay methodize wrap
//Extend Function prototype through the extend method of Object object Object.extend(Function.prototype, (function() { var slice = Array.prototype.slice; //Add args to array and return array, internal method function update(array, args) { var arrayLength = array.length , length = args.length; while (length--) array[arrayLength length] = args[length]; return array; } //Basically the same as the update method, but different Change the incoming parameter array and return a new array function merge(array, args) { array = slice.call(array, 0); return update(array, args); } //Format the parameters of the function into an array and return function argumentNames() { var names = this.toString().match(/^[s(]*function[^(] *(([^)]*))/)[1] .replace(///.*?[rn]|/*(?:.|[rn])*?*//g, ' ') .replace(/s /g, '').split(',');
return names.length == 1 && !names[0] ? [] : names; } //Bind the context of the execution function to context function bind(context) { if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this ; var __method = this, args = slice.call(arguments, 1); return function() { var a = merge(args, arguments); return __method.apply(context , a); } } //Basically similar to bind, that is, ensuring that the first parameter passed in must be the event object function bindAsEventListener(context) { var __method = this, args = slice.call(arguments, 1); return function(event) { var a = update([event || window.event], args); return __method.apply( context, a); } } //curry is the name of a mathematician. The function of this method is to continuously pass in parameters. You will know by looking at the specific example below function curry() { if (!arguments.length) return this; var __method = this, args = slice.call(arguments, 0); return function() { var a = merge(args, arguments); return __method.apply(this, a); } } //Simple encapsulation of the window.setTimeout function function delay(timeout) { var __method = this, args = slice.call(arguments, 1); timeout = timeout * 1000 return window.setTimeout(function() { return __method.apply(__method, args) ; }, timeout); } //Equivalent to delay(0.01) function defer() { var args = update([0.01], arguments); return this.delay.apply(this, args); } //Use wrapper to wrap the function to be called to implement a simple AOP function function wrap(wrapper) { var __method = this; return function() { var a = update([__method.bind(this)], arguments); return wrapper.apply(this, a); } } //Display the current context as the first parameter of the incoming call method function methodize() { if (this._methodized) return this._methodized; var __method = this ; return this._methodized = function() { var a = update([this], arguments); return __method.apply(null, a); }; } //Return external callable function return { argumentNames: argumentNames, bind: bind, bindAsEventListener: bindAsEventListener, curry: curry, delay: delay , defer: defer, wrap: wrap, methodize: methodize } })());
update, merge method: because it is I won’t go into details about the internal methods. You can basically understand the argumentNames method by looking at the source code: basically uses regular expressions to propose the parameter list in the method, and deletes spaces and some Special characters, then use ',' to split, and finally return the parameter array. I don't understand what is the use of the condition of finally returning names.length == 1? I gave it a try and it had no effect. If you know anything, tell me. Let’s take a look at an example:
bind method: First determine the number of parameters passed in. At least one context parameter must be passed in. If the bind() method is called directly, the original function object will be returned. It's the same as not calling it. The prototype of the bind method is like this: bind(thisObj[, arg...]) -> Function. The first parameter can be followed by optional parameters. In the bind method, the args variable is used to store everything except the first parameter. All other parameters except one parameter: args = slice.call(arguments, 1); var __method = this. This sentence means to set the __method variable to the current function. It will be clearer through examples. These:
var obj = { name: ' A nice demo', fx: function() { alert(this.name); } }; window.name = 'I am such a beautiful window!'; function runFx( f) { f(); } //where __method is equivalent to obj.fx var fx2 = obj.fx.bind(obj); runFx(obj.fx); //I am such a beautiful window! runFx(fx2); //A nice demo /* If we don’t call f() inside the runFx function, but call obj.fx() directly outside Then the result will be 'A nice demo'. In fact, if we write like this: var f=obj.fx;f(); we will also get 'I am such a beautiful window!'. Through the above example, we should be able to see the concept of context: obj.fx(); //The context is: obj f(); //The context is: window You can see The context is actually the object before the last '.'. If the function is called directly, the context is window */
Finally, an anonymous function applied to the context is returned. Note: The arguments in var a = merge(args, arguments); and the arguments in args = slice.call(arguments, 1); are different. Take a look at the example:
var obj = { name : 'A nice demo', fx: function() { alert(this.name 'n' $A(arguments).joi(', ')); } }; //[1,2,3] here is slice.call(arguments, 1); the arguments inside var fx2 = obj.fx.bind(obj, 1, 2, 3); //[4,5] here is merge(args, arguments); the arguments inside fx2(4, 5); // Alerts the proper name, then "1, 2, 3, 4 , 5"
bindAsEventListener method: This method is similar to bind. The main difference is this sentence: var a = update([event || window.event] , args); always ensure that the first parameter of the bound function is the event object. Take a look at the example:
var obj = { name: 'A nice demo' }; function handler(e) { var data = $A(arguments); data.shift(); alert(this.name 'nOther args: ' data. join(', ')); } handler.bindAsEventListener(obj, 1, 2, 3); //==================== ===
curry method: I personally feel that the example given in the help document for this method is not good. Here is another example, which will be clear at a glance:
var F=function(){alert(Array.prototype.slice.call(arguments,0).join(' '))}; F. curry('I').curry('am').curry('never-online').curry('http://www.never-online.net')(); //I am never -online http://www.never-online.net
delay and defer methods: Basically, it is a simple encapsulation of window.setTimeout. The time unit is seconds. Take a look at the example:
// clearing a timeout var id = Element.hide.delay(5, 'foo'); window.clearTimeout(id);
wrap method: Returns a function “wrapped” around the original function. Function#wrap distills the essence of aspect-oriented programming into a single method, letting you easily build on existing functions by specifying before and after behavior, transforming the return value, or even preventing the original function from being called. This sentence means: var a = update([__method.bind(this)], arguments); Just pass the wrapped function into the wrapping function as the first parameter. Take a look at the example:
function wrapped(){ alert('wrapped'); } //You can call the original function before or after the wrapper. Isn’t it a bit like AOP? var wrapper=wrapped.wrap(function(oldFunc,param){ //oldFunc() alert(param); oldFunc(); });
//wrapper,wrapped wrapper("wrapper");
methodize method: Takes a function and wraps it in another function that, at call time, pushes this to the original function as the first argument. This method first checks whether the method to be methodized has been methodized, and checks through the internal variable this._methodized, Finally What the methodize function returns is actually this._methodized. This sentence: var a = update([this], arguments); is the key. It can be seen that this is passed as the first parameter to the original function. Just look at the example and you will understand:
// start off with a simple function that does an operation // on the target object: var fn = function(target, foo) { target.value = foo; }; var object = {}; // original The method fn(object, 'bar'); object.value //-> 'bar' //After calling methodize, it can be seen that the first parameter target of the fn function becomes object object.fnMethodized = fn.methodize(); object.fnMethodized('boom!'); object.value //-> 'boom!'
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn