Heim  >  Artikel  >  Web-Frontend  >  Prototype Function对象 学习_prototype

Prototype Function对象 学习_prototype

WBOY
WBOYOriginal
2016-05-16 18:50:161131Durchsuche

这个对象就是对function的一些扩充,最重要的当属bind方法,prototype的帮助文档上特意说了一句话:Prototype takes issue with only one aspect of functions: binding.其中wrap方法也很重要,在类继承机制里面就是利用wrap方法来调用父类的同名方法。
argumentNames
bind
bindAsEventListener
curry
defer
delay
methodize
wrap

复制代码 代码如下:

//通过Object对象的extend方法对Function的prototype进行扩展
Object.extend(Function.prototype, (function() {
var slice = Array.prototype.slice;
//把args添加到array后面,并返回array,内部方法
function update(array, args) {
var arrayLength = array.length, length = args.length;
while (length--) array[arrayLength + length] = args[length];
return array;
}
//基本和update方法一样,但是不改变传入参数array,返回一个新的array
function merge(array, args) {
array = slice.call(array, 0);
return update(array, args);
}
//把函数的参数格式化成数组,并返回
function argumentNames() {
var names = this.toString().match(/^[\s\(]*function[^(]*\(([^)]*)\)/)[1]
.replace(/\/\/.*?[\r\n]|\/\*(?:.|[\r\n])*?\*\//g, '')
.replace(/\s+/g, '').split(',');

return names.length == 1 && !names[0] ? [] : names;
}
//把执行函数的上下文绑定到context
function bind(context) {
if (arguments.length var __method = this, args = slice.call(arguments, 1);
return function() {
var a = merge(args, arguments);
return __method.apply(context, a);
}
}
//基本和bind差不多,就是保证传入的第一个参数一定是event对象
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是一个数学家的名字,这个方法的作用就是可以连续的传入参数,看下面的具体例子就知道了
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);
}
}
//window.setTimeout函数的简单封装
function delay(timeout) {
var __method = this, args = slice.call(arguments, 1);
timeout = timeout * 1000
return window.setTimeout(function() {
return __method.apply(__method, args);
}, timeout);
}
//相当于delay(0.01)
function defer() {
var args = update([0.01], arguments);
return this.delay.apply(this, args);
}
//用wrapper包装将要调用的函数,实现了简单的AOP功能
function wrap(wrapper) {
var __method = this;
return function() {
var a = update([__method.bind(this)], arguments);
return wrapper.apply(this, a);
}
}
//把当前上下文作为第一个参数显示的传入调用的方法
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 {
argumentNames: argumentNames,
bind: bind,
bindAsEventListener: bindAsEventListener,
curry: curry,
delay: delay,
defer: defer,
wrap: wrap,
methodize: methodize
}
})());

update,merge方法:由于是内部方法,就不详细说了,看源代码基本上能看懂
argumentNames方法:
基本就是利用正则表达式提出方法里面的参数列表,并且删除空格和一些特殊字符,然后用','进行分割,最后返回参数数组,我不明白最后返回 names.length == 1 这个条件有什么用?我试了试,去了也没什么影响,知道的告诉我一下。下面看一下示例:
复制代码 代码如下:

var fn = function(foo, bar) { return foo + bar; };
fn.argumentNames(); //-> ['foo', 'bar']
Prototype.emptyFunction.argumentNames(); //-> []

bind方法:
首先判断传进来的参数个数,至少要传进来一个context参数,如果直接调用bind()方法,那么将返回原来的函数对象。就相当于没调用一样。
bind方法的原型是这样的:bind(thisObj[, arg...]) -> Function,第一个参数后面可以跟可选的参数,在bind方法里面用args变量存储了除了第一个参数之外的所有其它参数:args = slice.call(arguments, 1);
var __method = this,这句话的意思是把__method变量设为当前的函数,通过例子说明更清楚些:
复制代码 代码如下:

var obj = {
name: 'A nice demo',
fx: function() { alert(this.name); }
};
window.name = 'I am such a beautiful window!';
function runFx(f) { f(); }
//其中__method就相当于obj.fx
var fx2 = obj.fx.bind(obj);
runFx(obj.fx); //I am such a beautiful window!
runFx(fx2); //A nice demo
/*
这里如果我们不在runFx函数里面调用f(),而是直接在外面调用obj.fx()那么得到的结果将是'A nice demo'。
其实如果我们这样写:var f=obj.fx;f();那也将得到‘I am such a beautiful window!'。
通过上面的例子,我们应该能看出上下文的概念:
obj.fx(); //上下文为:obj
f(); //上下文为:window
可以看出上下文其实就是最后一个'.'之前的那个对象,如果直接调用函数则上下文为window
*/

最后返回一个应用于context上下文的匿名函数。
注意:var a = merge(args, arguments);这句话里面的arguments和args = slice.call(arguments, 1);里面的arguments是不一样的。看一下例子:
复制代码 代码如下:

var obj = {
name: 'A nice demo',
fx: function() {
alert(this.name + '\n' + $A(arguments).joi(', '));
}
};
//这里的[1,2,3]就是slice.call(arguments, 1);里面的arguments
var fx2 = obj.fx.bind(obj, 1, 2, 3);
//这里的[4,5]就是merge(args, arguments);里面的arguments
fx2(4, 5);
// Alerts the proper name, then "1, 2, 3, 4, 5"

bindAsEventListener方法:
这个方法和bind差不多,最主要差别在这句:var a = update([event || window.event], args);总是保证绑定的函数第一个参数为event对象。看一下示例:
复制代码 代码如下:

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方法:
这个方法的个人觉得帮助文档上给的例子不好,下面给出另一个示例,一看就明白了:
复制代码 代码如下:

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和defer方法:
基本就是window.setTimeout的简单封装,时间单位为秒,看一下示例:
复制代码 代码如下:

// clearing a timeout
var id = Element.hide.delay(5, 'foo');
window.clearTimeout(id);

wrap方法:
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.
这句话:var a = update([__method.bind(this)], arguments);的意思就是把被包装的函数当作第一个参数传入包装函数,看一下示例:
复制代码 代码如下:

function wrapped(){
alert('wrapped');
}
//可以在wrapper之前调用原函数或者之后调用,是不是有点AOP的意思了
var wrapper=wrapped.wrap(function(oldFunc,param){
    //oldFunc()
    alert(param);
    oldFunc();
});

//wrapper,wrapped
wrapper("wrapper");

methodize方法:
Takes a function and wraps it in another function that, at call time,
pushes this to the original function as the first argument.
这个方法先检查将要被methodize的方法是否已经methodize过了,通过内部的变量this._methodized做检查,
最后methodize函数返回的其实就是this._methodized。
这句话:var a = update([this], arguments);是关键,可以看出把this当成第一个参数传到这个原始函数中了。看一下示例就明白了:
复制代码 代码如下:

// start off with a simple function that does an operation
// on the target object:
var fn = function(target, foo) { target.value = foo; }; var object = {};
// 原始的方法
fn(object, 'bar');
object.value //-> 'bar'
//调用methodize之后,可以看出fn函数第一个参数target变成了object
object.fnMethodized = fn.methodize();
object.fnMethodized('boom!');
object.value //-> 'boom!'
Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn