Javascript 函数参数名妙用(区分函数参数名称)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/petrelselina/article/details/50803231

首先,我们看两个函数

var perform1 = function (dog) {
            console.log(dog.name);
    };

var perform2 = function (cat) {
            console.log(cat.name);
    };


这两个函数很难想象他们调用会有不一样的效果,他们唯一的区别就是参数名称的不同。然而很多流行的框架,你传入的匿名函数,你自己都不知道参数应该是什么,什么顺序,所以在大部分框架中就实现了根据参数名来赋值的效果。


比如说,我们有一个Performance类,有个perform方法,而这个perform方法让用户自己定义。也就是说,用户需要自己定义个函数,然后赋值给Performance.perform.用户想实现如下的功能:

var performance = new Performance();
        performance.perform = function (dog) {
            console.log(dog.name);
        };
        performance.do();

        performance.perform = function (cat) {
            console.log(cat.name);
        };
        performance.do();

        performance.perform = function (cat, dog) {
            console.log(cat.name + "  " + dog.name);
        };
        performance.do();

用户不用在乎参数的顺序,只需要提供一定格式的参数名,比如我用cat做参数名,那请给我一个cat的对象,用dog就给我dog对象,如果参数cat dog都有,那请给我两个对象。

可能你会觉得这种需求还是不怎么明白,那我举个大家熟悉的例子

jQuery.ajax({
            data: {},
            success:function(data,state){
        
            },
            error: function (xhr,msg,obj) {

            }
        });


这是JQuery的ajax方法,它其中的sucess和error是需要用户自己定义的函数,但是函数的参数是固定死的,也就是说在error函数中,第一个参数就是xhr对象,第二个参数就是错误信息,用户不能颠倒顺序,或者漏写前面某个参数而去使用后面的参数。比如,我想直接弹出错误信息:

error: function (msg) {
    alert(msg);
 }

可是实际结果是弹出xhr实例的toString()结果。

有人可能会说,这是常识吧,所有程序都是这样执行的啊。

实际上,用过Angular的人都会发现,在使用Angular的过程中,传参从来不用考虑第一个参数应该是什么。$http参数放在第一个或者第二个它都是$http实例,用户在factory中定义了一堆service,也只需要通过参数名就能获取到,实际上这种体验要明显好很多。

然而怎么去实现呢?第一点就是怎么获取参数名称。其实javascript的每个函数都有toString()方法,我们可以从这个方法入手。

args = fn.substring(fn.indexOf('(') + 1, fn.indexOf(')')).split(',');
当我们得到函数toString()后的字符串fn后,就可以通过上面截取字符串的方式获得参数名集合。

比如,我们拿到的参数里有名称为dog的参数,那么我们就取this["dog"]从而拿到dog对象,用它当参数去调用函数。

下面代码就是实现文章一开始提到dog还是cat得问题。

var Performance = function () {
            this.dog = { name: 'dog' };
            this.cat = { name: 'cat' };
            this.do = function () {
                var fn = this.perform.toString(),
                    args = fn.substring(fn.indexOf('(') + 1, fn.indexOf(')')).split(',');

                for (var i = 0; i < args.length ; i++) {
                    args[i] = this[args[i].trim()];
                }

                this.perform.apply(this, args);
            }
        };
 
 


一开始我比较纠结如何将一个数组当参数传递给一个方法,后来想起了apply方法,这个方法本质上是为了替换一个函数中this的实例的,但是它第二个参数可以接受一个参数数组,这便是我们这里需要的。

同时,我也查看了Angular的源码,确实,和我的思路是一样的。


猜你喜欢

转载自blog.csdn.net/petrelselina/article/details/50803231