jquery中如何将函数字符串放入数组组变量并执行?

javascript、jQuery函数定义和调用方法
一、javascript
1、var aaa=function(){...}
var 方式定义的函数,不能先调用函数,后声明,只能先声明函数,然后调用。
2、function aaa(){...}
function方式定义函数可以先调用,后声明。
&script language="JavaScript" type="text/javascript"&&&&
&&&&&&&&&&& //aaa();这样调用就会出错&&&
&&&&&&&&&&& var aaa = function(){&&&
&&&&&&&&&&&&&&& alert("A");&&&
&&&&&&&&&&& }&&&
&&&&&&&&&&& aaa();//这样就不会出错&&&
&&&&&&&&&&&&&&&
&&&&&&&&&&& //先调用后声明&&&
&&&&&&&&&&& bbb();&&&
&&&&&&&&&&& function bbb(){&&&
&&&& &&&&&&&&&&&alert("bb");&&&
&&&&&&&&&&& }&&&
二、jQuery
1、定义:$.setActive = function (toFindName) {&&& $(".tab_content").hide(); //Hide all content& }
调用:$.setActive(toFindName);
或:$.postJSON = function(url, data, callback) {//这里有回调函数
& &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& $.post(url, data, callback, "json");
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& & };
调用:$.postJSON('/post/getsecurejsonpost',{}, function(data) {});
&& jQuery.fn.setApDiv=function () {
&&&&&&& //apDiv浮动层显示位置居中控制
&&&&&&& var wheight=$(window).height();
&&&&&&& var wwidth=$(window).width();
&&&&&&& var apHeight=wheight-$("#apDiv").height();
&&&&&&& var apWidth=wwidth-$("#apDiv").width();
&&&&&&& $("#apDiv").css("top",apHeight/2);
&&&&&&& $("#apDiv").css("left",apWidth/2);
调用:$("#apDiv").setApDiv();
&&&&& //jQuery 应用扩展
&&&& &jQuery.extend({
&&&&&&&&&&&&& // 设置 apDiv
&&&&&&&&&&& setApDiv:function () {
&&&&&&&&&&& //apDiv浮动层显示位置居中控制
&&&&&&&&&&& var wheight=$(window).height();
&&&&&&&&&&& var wwidth=$(window).width();
&&&&&&&&&&& var apHeight=wheight-$("#apDiv").height();
&&&&& &&&&&&var apWidth=wwidth-$("#apDiv").width();
&&&&&&&&&&& $("#apDiv").css("top",apHeight/2);
&&&&&&&&&&& $("#apDiv").css("left",apWidth/2);
&&&&&&&&&&& }
调用:$.setApDiv();
一种如$.extend({'aa':function(){}}),这种调用时就是这样$.aa(),另一种如$.fn.extend({'aa':function(){}}),这种调用时就得这样,$(this).aa()
&注:或之后的片段引用自/chengxiaohui/articles/1914232.html,最近在对比整理js、jQuery等,非常感谢该文作者。
实际上不管是jquery还是Extjs,本质上都是javascript,所以文件中用原生态的js写的函数,一样都是可以调用的。
> 本站内容系网友提交或本网编辑转载,其目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。如涉及作品内容、版权和其它问题,请及时与本网联系,我们将在第一时间删除内容!
代码示例如下: &!doctype html& &html lang=&en&& &head& &meta charset=&UTF-8&& &meta name=&Generator& content=&EditPlus?& ...
二维数组作为参数的函数的定义及调用方法 Geophoenix C语言编程的过程中,不可避免的会碰到二维或二维以上的数组作为函数的形参的情况,在以前的编程过程中,习惯了动态数组的应用,很是使用直接定义高维数组.最近在编程的过程中就碰到了这个问题:有如下的测试程序: voidtest(double
x,int Row,int Col); voidtest(do ...
这篇文章主要介绍了javascript中函数作为参数调用的方法,实例分析了函数作为操作调用的原理与相关技巧,需要的朋友可以参考下本文实例讲述了javascript中函数作为参数调用的方法.分享给大家供大家参考.具体分析如下: 先来看示例: function Map(){ var obj = {}; this.put = function(key, value ...
内部函数:定义在另一个函数中的函数 例如: &script& function outer(){ function inner(){ } } &/script& inner()就是一个被包含在outer()作用域中的内部函数,所以: 在outer()内部调用inner()函数有效, 在outer()外部调用inner()函数无效. 例 ...
JavaScript 申明函数的三种方法 每个函数就是一个对象一一.申明函数的三种方法 (Declaring a Function) 方法一:function functionName([parameters]){functionBody}; Example D1 代码如下: function add(a, b) { return a+b; } alert( ...
这篇文章主要介绍了javascript用函数实现对象的方法,涉及javascript函数使用技巧,需要的朋友可以参考下本文实例讲述了javascript用函数实现对象的方法.分享给大家供大家参考.具体实现方法如下: &html xmlns=&http://www.w3.org/1999/xhtml&& &head& ...
这篇文章主要介绍了python使用multiprocessing模块实现带回调函数的异步调用方法,实例分析了multiprocessing模块异步调用的相关使用技巧,需要的朋友可以参考下本文实例讲述了python使用multiprocessing模块实现带回调函数的异步调用方法.分享给大家供大家参考.具体分析如下: multipressing模块是pytho ...
这篇文章阐述的是一种函数式编程(functional-programming)设计模式,我称之为惰性函数定义(Lazy Function Definition).我不止一次发现这种模式在JavaScript中大有用处,尤其是编写跨浏览器的.高效运行的库之时. 热身问题 编写一个函数foo,它返回的是Date对象,这个对象保存的是foo首次调用的时间. 方法一 ...所有回答(3)
它是有一个默认参数的,一般都是如下形式
$.fn.functionName= function(opts) {
var defaults = {
var options = $.extend(defaults, opts);//todo:....本质还是可选参数,也是给了一些默认值,你进源码看看就知道了
园豆:1673
JS的函数中,可以用arguments接收所有的方法参数,只要你传了。
园豆:30522
园豆:30522
定义函数的时候参数叫做形参,调用函数的时候,参数叫做实参。
在执行函数之前,有一个初始化的准备工作:
其中一个步骤是给形参赋值:实参从左到右依次赋值给形参。实参个数多的话肯定没问题,每一个形参都得到值了,要是实参的个数少,那么剩下的形参值就是undefined
还有一个步骤是准备Arguments Object,也就是楼上说的arguments对象,它有三个属性:
1. callee --- 当前函数的引用,可以用来实现递归调用
2. length --- 实参的个数,也是arguments数组的长度
3. arguments数组的值,也是所有实参依次组成的数组,下标从0开始
另外还有一个特性需要注意:arguments数组和形参是共享数据的,修改一处,另一处也会改变。共享也是有限制的,假如形参有x,y,z三个,但是实参只有两个5,7。这样的话arguments数组的长度只有2,所以只有x与arguments[0],z与arguments[1]共享,z不存在共享,应为没有arguments[2]
园豆:1460
&&&您需要以后才能回答,未注册用户请先。[调试日志]用php函数var_export把多维数组file_put_contents写入并打印到日志,以方便调试之多维数组,用php5中的var_export函数示例,顺带介绍http_build_query
引用地址:
注意: 该地址仅在今日23:59:59之前有效
一行解决写入日志:
file_put_contents(&/tmp/jack.txt&, var_export($layReturnArr,TRUE),FILE_APPEND);
一行完成Curl的POST输出:
echo &curl -d\&&.http_build_query($data).&\& &.$
临时调试:
$result= var_export ( $_POST,True);
file_put_contents(&/tmp/jack.txt&,$result,FILE_APPEND);
路径变量:
&&&&&&&&$uploadSliceLogName = &/data/htdocs/xiyou_devel/data/logs/&.date(&Ymd&).&/uploadedSliceReceiveInfo.txt&;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&file_put_contents($uploadSliceLogName, var_export($_REQUEST,TRUE),FILE_APPEND);
$file_string = var_export ( $_POST,True);
file_put_contents(&/tmp/var_export.txt&,$file_string,FILE_APPEND);
在调试上传文件时,如苹果Android等(这一行来自PHP高级编程:岁月如哥【俗称:膘哥】(191295**)它提供的。 09:58 AM ):
@file_put_contents(&log.txt&,var_export($_GET,$_POST,$_FILES,file_get_contents(&php://input&),true),FILE_APPEND);
后记:岁月如哥(191295**)&&15:20:48你要看一下ios下。如果图片过大。或者。。。有些异常情况发生的时候。$_FILES都为空的。这些我们都遇到过收到的内容全部为空。而且会导致其他所有的变量都为空回忆未来-向东-Jàck(3726476**)&&15:23:51那有可能是这个问题,我用上面这个直接打Post有值,呵呵。膘哥说得对,是可能图片太大了。调试:
touch /tmp/var_export.txt
chmod -R 777 /tmp/var_export.txt
tail -f&&/tmp/var_export.txt
就能看到调试信息。看了一下phpcms的源码:&&function cache_write($file, $string, $type = 'array')&&{&&&&&& if(is_array($string))&&&&&& {&&&&&&&&&& $type = strtolower($type);&&&&&&&&&& if($type == 'array')&&&&&&&&&& {&&&&&&&&&&&&&& $string = &&?php\n return &.var_export($string,TRUE).&;\n?&&;&&&&&&&&&& }&&&&&&&&&& elseif($type == 'constant')&&&&&&&&&& {&&&&&&&&&&&&&& $data='';&&&&&&&&&&&&&& foreach($string as $key =& $value) $data .= &define('&.strtoupper($key).&','&.&& addslashes($value).&');\n&;&&&&&&&&&&&&&& $string = &&?php\n&.$data.&\n?&&;&&&&&&&&&& }&&&&&& }&&&&&& $strlen = file_put_contents(PHPCMS_CACHEDIR.$file, $string,FILE_APPEND);&&//最好加上FILE_APPEND,否则tail -f出现tail: /tmp/friendviews.txt: file truncated&& 参看:http://www.xiangdong.org/blog/post/1614/&&&&&& chmod(PHPCMS_CACHEDIR.$file, 0777);&&&&&&&& return $&&}
可以看到var_export 解释下var_export (PHP 4 &= 4.2.0, PHP 5)var_export -- 输出或返回一个变量的字符串表示描述mixed var_export ( mixed expression [, bool return])此函数返回关于传递给该函数的变量的结构信息,它和 var_dump() 类似,不同的是其返回的表示是合法的 PHP 代码。您可以通过将函数的第二个参数设置为 TRUE ,从而返回变量的表示。 应用场景:假如我们看到一个数组是多维的,其实通过serialize之后写入文件 读出来之后unserialize也可以,但我们只是想看看数组里面是什么,但又不想打印到页面上。实例:&?php&&&&&&&&$a = array ( 1 , 2 , array ( &a& , &b& , &c& ));&&&&&&&&$file_string = var_export ( $a,True);&&&&&&&&var_dump($file_string);&&&&&&&&file_put_contents(&/tmp/friendviews.txt&,$file_string,FILE_APPEND);&&&&&&&&?&tail -f /tmp/friendviews.txt结果:array (&&0 =& 1,&&1 =& 2,&&2 =& &&array (&&&&0 =& 'a',&&&&1 =& 'b',&&&&2 =& 'c',&&),)http_build_query 把数组整成一个get串:
file_put_contents(&/tmp/jack.txt&, &\n&.http_build_query($arg).&\n&,FILE_APPEND);
作者:@地址:版权所有。转载时必须以链接形式注明作者和原始出处及本声明!
最后编辑: justwinit 编辑于 10:34
[9/9]北京市海淀区中关村理想国际大厦18层 Address:Sina 18th floor Ideal plaza Zhongguancun Haidain
Beijing 100080, P.R.China
[1/9]深圳南山腾讯大厦8楼 Address:Tencent Plaza High-tech One Road, Middle Zone, High-new Science & Technology Park, Nanshan Distrcit, Shenzhen City, Guangdong Province 518057, P.R. China
[2/9]深圳南山腾讯大厦旁大族激光大厦三楼 Address:Han's Building,Kejizhongyi Avenue, Hi-tech Pack,Nanshan District, Shenzhen City, Guangdong Province 518057, P.R.China
[2012/10-Now]北京海淀区西三环中路10号望海楼B座7层央视国际网络有限公司 Address:Seaview floor, Haidian District No.10,West Sanhuan Road,Beijing 100142, P.R.ChinaJS中给函数参数添加默认值-爱编程
JS中给函数参数添加默认值
最近在Codewars上面看到一道很好的题目,要求写一个函数defaultArguments,用来给指定的JS函数的参数添加默认值。举例来说就是:
// foo函数有一个参数,名为x
var foo_ = defaultArguments(foo, {x:3});
// foo_是一个函数,调用它会返回foo函数的结果,同时x具有默认值3
下面是一个具体的例子:
function add(a, b) {return a+b;}
// 给add函数的参数b添加默认值3
var add_ = defaultArguments(add, {b : 3});
// 这句代码相当于调用add(2, 3),因此返回5
add_(2); // 5
// 而这句代码由于完整地给出了a、b的值,所以不会用到b的默认值,因此返回12
add_(2, 10); // 12
之所以说这是一个好题目,是因为它和那些单纯考算法的题有很大差别,完成它需要你对JS的很多知识点有相当深入的了解。包括获取函数的形参列表、运行时实参、正则表达式、高阶函数、管道调用等,以及其他一些细小的知识点。
我在刚拿到这个题目时的感觉是无从下手,因为之前没有碰到过类似的题目,完全没有过往的经验可以借鉴。但是经过简单的思考,虽然还有很多问题需要解决,但已经有了一个初步的思路,这个函数的框架大体上应该是这样的:
function defaultArguments(func, defaultValues) {
// step 1: 获得形参列表
var argNames = ...;
// 返回一个wrapper函数,其中封装了对原函数的调用
return function() {
// step 2: 获得运行时实参
var args = ...;
// step 3: 用默认值补齐实参,没有定义默认值的为undefined
// step 4: 调用原函数并返回结果
return func.apply(null, args);
思路还是比较清楚的,函数defaultArguments应该返回一个函数,这个函数用来对func函数的调用进行包装,从而在调用func函数之前对传入的参数进行处理,用默认值替换那些未传入值的参数。由于默认值是用形参名称来指定的,而不是参数在列表中的顺序,所以需要获得形参的列表,才能判断为哪些参数指定了默认值。
Step 1:获得形参列表
刚开始准备写代码就遇到了第一个难题:怎么才能获得一个函数的形参列表呢?
这个问题确实让我抓耳挠腮了一把,最后想出了一个方法。我们知道JS中的所有对象都有toString()方法,函数是一个function对象,那么function对象的toString()返回什么呢?对了,就是函数的定义代码。例如add.toString()将返回&function add(a, b) {return a+b;}&。
拿到了函数定义的代码,获取形参列表的方法也就有了,只需把括号里的内容取出来,然后以逗号进行拆分就可以了(注意要去除参数名前后的空格)。
(后来再次阅读问题描述的时候发现问题中是有提示可以用Function.toString()方法获得形参列表的,没认真读题的悲哀啊。)
要取出形参列表,一种方法是先找到左右括号的索引,然后用substring()来取;另一种是用正则表达式来取。我使用的是正则表达式的方式:
var match = func.toString().match(/function([^\(]*)\(([^\)]*)\)/);
var argNames = match[2].split(',');
这个正则表达式的匹配过程如下图:
第一个分组(group 1)用来匹配左括号前面的函数名部分,第二个分组(group 2)用来匹配括号中的形参列表。注意函数名和形参列表都不是必须的,因此匹配时使用的是*号。match()方法返回的是一个数组,第一个元素是匹配到的完整结果,后面的元素依次为各个捕获分组所匹配到的内容,所以形参列表所在的group 2分组对应返回结果的第三个元素。
Step 2:获得运行时实参
形参列表有了,接下来就是获得实参了。因为函数不是我们自己定义的,我们无法用形参名称来引用实参,但是JS为每个函数的调用隐式提供了一个变量arguments,用来获取传入的实参。关于arguments这里就不多说了,相信会用JS的都比较了解。
Step 3:用默认值补齐实参
一开始我的做法是,遍历形参数组,如果发现对应的参数值为undefined,就检查是否为该参数提供了默认值,如果是就将其替换为默认值。代码类似于下面这样:
var args = [];
for (var i = 0; i & argNames. i++) {
if (arguments[i] !== undefined) {
args[i] = arguments[i];
args[i] = defaultValues[argNames[i]];
但这段代码在其中一个测试用例上失败了 。那个用例显式地传入了一个undefined值。就像这样:&add_(2, undefined);&,此时应该返回NaN,而这时我会把b参数用默认值替换为3,所以返回的是5。
我意识到不能用这种方法来替换参数的默认值。思考后发现,能够提供默认值的只能是最后若干个参数,你无法为前面的某个参数提供默认值而不为它之后的参数提供默认值。例如对于函数add(a,b)来说,是无法做到只为参数a提供默认值的。如果你调用&defaultArguments(add, {a:1});&的话,此时好像是a有了默认值1而b没有默认值,但实际上此时的b也有隐含地有了默认值undefined,因为你永远无法做到只使用a的默认值而给b传入一个具体的值。
比如你想使用a的默认值,同时想给b传入2,这是无法做到的。如果你这样:&add_(2)&,实际上是给a指定了参数值2。而如果你想这样:&add_(undefined, 2)&,虽然确实把2传给了b,但此时却同时为a指定了undefined。
所以,默认参数只能出现在形参列表的最后若干个参数中。如果我们为某个参数指定了默认值但却没有为它后面的参数指定,此时实际上相当于它后面的那些参数的默认值为undefined。就像上面例子中的a、b那样。
实际上这个规则很早就了解了,也在其他语言中使用过,但却没有认真思考过其中包含的逻辑。直到解答这个问题的时候才算彻底了解了。
根据上面的结论,就可以很容易地修改上面的代码了,只需为形参列表中没有传入值的最后若干个参数使用默认值即可:
var args = Array.prototype.slice.call(arguments);
for (var i = arguments. i & argNames. i++) {
args[i] = defaultValues[argNames[i]];
完整代码如下:
var defaultArguments = function(func, defaultValues) {
if (!defaultValues) return
var match = func.toString().match(/function[^\(]*\(([^\)]*)\)/);
if (!match || match.length & 2) return
var argNameStr = match[1].replace(/\s+/g, ''); // remove spaces
if (!argNameStr) return
var argNames = argNameStr.split(',');
var wrapper = function() {
var args = Array.prototype.slice.call(arguments);
for (var i = arguments. i & argNames. i++) {
args[i] = defaultValues[argNames[i]];
return func.apply(null, args);
这就是我当时根据题目要求所写的第一个程序,自认为已经不错了,自己编写的几个测试用例也能顺利通过,于是信心满满地点击了提交,但是&&失败了。未通过的用例大概是这样的:
var add_ = defaultArguments(add, {b:9});
add_ = defaultArguments(add_, {a:2, b:3});
结果应该是13,因为这时候b的默认值已经重置为2了,但上面的程序返回的却是19。原因是defaultArguments()返回的那个wrapper函数已经丢失了原函数的形参列表。例如add()函数的形参列表应该是&a,b&,但如果我们在该测试用例的第一条语句后执行add_.toString(),返回的将是wrapper函数的定义,而不是add函数的,但wrapper函数却并没有定义形参。
为了解决这个问题,我尝试了好几种方案。首先考虑使用Function类来构造一个function对象,因为Function的构造函数接受的是字符串类型的参数,并返回由该字符串构造的函数。前面若干个参数用来定义形参,最后一个参数则是函数体。例如:
var add = new Function('a', 'b', 'return a+b'); // function(a,b){return a+b}
但是问题来了,我如何才能将形参列表传给Function的构造函数呢?毕竟defaultArguments接收到的func函数的形参个数是不确定的,但Function的构造函数又不接受数组作为参数。问题到此似乎陷入了僵局,忽然,我想到如果不用new呢?把Function的构造函数当成普通函数调用,这样的话我就可以使用apply()方法将一个数组作为参数传递给它了。经过试验,发现这样确实可以,下面的代码确实返回了和使用new时一样的function对象:
Function.apply(null, ['a', 'b', 'return a+b']);
于是我用这种方法动手改造我的代码,但是却发现行不通,因为wrapper函数的内部需要通过闭包来使用外层defaultArguments函数的func和defaultValues参数的值,但是经过Function构造的函数所在的却是全局作用域,无法在当前上下文中形成闭包。此路不通。
虽然这个方案失败了,但我对Function构造函数的理解却更进了一步,也算是小有收获。
第二种方案是使用eval()来构造一个function对象。该方案并没有实施,因为我知道eval()也会使构造的代码脱离当前作用域,因此也无法形成闭包。
至此问题再度陷入了僵局。期间又尝试了数种方案但都行不通。忽然我灵机一动,实际上我们并不需要让wrapper的形参列表与func一致,只需让它的toString()返回的结果与func的形参列表一致即可,因为我们并不需要真正的反射wrapper本身,只是通过它的toString()来解析而已。因此,我们只需重写wrapper的toString()方法,让其返回func.toString()的值:
wrapper.toString = function() {
return func.toString();
一句代码就完美地解决了这个问题,心里着实有点小激动。于是再次信心满满地点击提交,本以为这次一定能顺利地通过,但是很不幸地再次遭遇了失败。这次的原因是:当传入的函数的形参列表中包含注释时会导致解析的形参不正确。例如:
function add(a, // 注释
b /* 注释 */) {
return a +
此时add.toString()返回的字符串中是包含这些注释的,如果不加处理,就会把注释的内容错误地当成形参的一部分,自然是不行的。不过这个问题比较简单,只需在匹配到括号中的内容后将注释去掉就可以了,使用合适的正则表达式调用replace()即可:
var argNameStr = match[1].replace(/\/\/.*/gm, '') // remove single-line comments
.replace(/\/\*.*?\*\//g, '') // remove multi-line comments
.replace(/\s+/g, ''); // remove spaces
这两个正则表达式就不再赘述了。修改后再次提交,这次终于通过了全部测试用例!撒花~~~撒花~~~
完整程序如下:
var defaultArguments = function(func, defaultValues) {
if (!func) return null;
if (!defaultValues) return
var match = func.toString().match(/function[^\(]*\(([^\)]*)\)/);
if (!match || match.length & 2) return
var argNameStr = match[1].replace(/\/\/.*/gm, '') // remove single-line comments
.replace(/\/\*.*?\*\//g, '') // remove multi-line comments
.replace(/\s+/g, ''); // remove spaces
if (!argNameStr) return
var argNames = argNameStr.split(',');
var wrapper = function() {
var args = Array.prototype.slice.call(arguments);
for (var i = arguments. i & argNames. i++) {
args[i] = defaultValues[argNames[i]];
return func.apply(null, args);
wrapper.toString = function() {
return func.toString();
到此还没有结束
虽然最终提交成功了,但回过头再仔细检查一下代码,发现还是有问题。例如对于下面的代码:
function add(a,b,c) { return a+b+c; }
var add_ = defaultArguments(add,{b:2,c:3});
// 修改c的默认值,注意此时b的默认值应该仍然为2
add_ = defaultArguments(add_,{c:10});
因为最终b和c的默认值分别为2和10,所以这段代码的结果应该是13,但实际得到的却是NaN。
这个问题在提交时没有被测试出来,看来原题的测试用例并不完善。要修复这个问题,就要先搞清楚原因。我们来看看当执行上面的代码时的过程是怎样的。
这段代码一共调用了2次defaultArguments,因此会生成2个wrapper,这两个wrapper是嵌套的。我们不妨把第一次生成的wrapper称为wrapper1,第二次的称为wrapper2。它们之间的关系如下图所示:
当最后调用&add_(1)&时,参数&1&会传给wrapper2,此时a的值为1,b和c都没有值。然后经过wrapper2的处理,会形成新的实参:&1, undefined, 10&并传给wrapper1。注意此时3个参数都是有值的,所以并不会用默认值替换,因此wrapper1会直接将它们传给func,因此func返回的是&1+undefined+10&,这个结果为NaN。整个过程如下图所示:
明白了原因,但是该怎么解决呢?我的方法是在wrapper上将defaultValues的值保存下来,下次调用时,先判断是否已经存在之前指定的默认值,如果存在,就将其合并到新的默认值里去。
// 如果之前保存过默认值,将其取出合并到新的defaultValues中
var _defaultValues = func._defaultV
if (_defaultValues) {
for (var k in _defaultValues) {
if (!defaultValues.hasOwnProperty(k)) {
defaultValues[k] = _defaultValues[k];
// 生成wrapper后,把defaultValues保存到wrapper中
wrapper._defaultValues = defaultV
如果此时再次运行,2次生成的wrapper对象将如下图所示:
wrapper2中的默认参数不再只有c=10,而是会将wrapper1中定义的b的默认值合并过来,从而不会再有之前的问题了。实际上通过此图还可以看出,此时的wrapper1对wrapper2来说已经用处不大了,因为有了新的默认参数,已经不再需要wrapper1中的默认参数了。wrapper1剩下的唯一的用处只是用来最终调用func函数而已。那么如果我们把初始的func函数也保存下来,在wrapper2中直接调用,就可以完全去掉wrapper1了。这只需添加两句代码:
// 如果有保存的func函数就取出来,从而省掉一层对wrapper的调用
func = func._original ? func._original :
// 生成wrapper后,保存func函数
wrapper._original =
这时运行上面的测试代码,wrapper2中就不再有wrapper1了。如下图所示:
至此,我觉得代码已经趋于完美了。最终的代码如下:
var defaultArguments = function(func, defaultValues) {
if (!func) return null;
if (!defaultValues) return
// 如果之前保存过默认值,将其取出合并到新的defaultValues中
var _defaultValues = func._defaultV
if (_defaultValues) {
for (var k in _defaultValues) {
if (!defaultValues.hasOwnProperty(k)) {
defaultValues[k] = _defaultValues[k];
// 如果有保存的func函数就取出来,从而省掉一层对wrapper的调用
func = func._original ? func._original :
var match = func.toString().match(/function[^\(]*\(([^\)]*)\)/);
if (!match || match.length & 2) return
var argNameStr = match[1].replace(/\/\/.*/gm, '') // remove single-line comments
.replace(/\/\*.*?\*\//g, '') // remove multi-line comments
.replace(/\s+/g, ''); // remove spaces
if (!argNameStr) return
var argNames = argNameStr.split(',');
var wrapper = function() {
var args = Array.prototype.slice.call(arguments);
for (var i = arguments. i & argNames. i++) {
args[i] = defaultValues[argNames[i]];
return func.apply(null, args);
// 重写wrapper的toString方法,返回原始func函数的toString()结果
wrapper.toString = function() {
return func.toString();
// 把原始的func函数和当前的默认值对象保存到wrapper中
wrapper._original =
wrapper._defaultValues = defaultV
这个问题看似简单,但实现起来却不简单。其中涉及到JS中的许多知识点,有些是平时不太会注意的。因此我在解题过程中也是一边思考一边实验一边查资料,最终才搞定了这个问题,并且我的答案比很多人的答案更优秀,心里的成就感还是挺高的。
最后,谢谢阅读,如有错误请务必指出。【完】
版权所有 爱编程 (C) Copyright 2012. . All Rights Reserved.
闽ICP备号-3
微信扫一扫关注爱编程,每天为您推送一篇经典技术文章。}

我要回帖

更多关于 jquery 数组变量 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信