zoukankan      html  css  js  c++  java
  • 添加事件时调用的方法的this又想指向其他对象

    1.应用案例:

            var Mouse = function () {

                // Look! no that = this!

                this.position = [0, 0];

                if (document.addEventListener) {

                    document.addEventListener('mousemove', ?);   //this.move?  

                } else if (document.attachEvent) {

                    document.attachEvent("onmousemove", ?);     //this.move?怎么放进去

                }

            };

            Mouse.prototype.move = function (arg1,arg2,event) {

                event = window.event || event;

                var x = event.pageX || event.offsetX,

            y = event.pageY || event.offsetY;

                this.position = position = [x, y];

                this.log(arg1,arg2);

            };

            Mouse.prototype.log = function (arg1, arg2) {

                console.log(arg1+","+arg2);

                console.log(this.position);

            };

            new Mouse();

    上面你知道'?'号那里要干嘛了吗?我想给document的mousemove绑定我的move方法,但是遇到难题了,这样的话,Mouse.prototype.move

    里的this就不会指向Mouse的对象,相信大家经常碰到这种问题.也许你早知道了怎么解决,但是有更快更简单的方法吗?答案是:

      Function.prototype.bind()这个神奇的玩意,但是ie6 7 8都不支持,一般现代浏览器都支持了,我们接下来要做的就是模仿他,

     这么好的方法当然要模仿它,怎么模仿见下面nothing的原创方法

        (function () {

                var proxy = function (fn, target) {

                    var proxy = function () {

                        if (2 < arguments.length) { //存在被代理的函数有参数的时候

                            var privateArgs = Array.prototype.slice.call(arguments, 2);

                          //从第二个开始取出来,[this,绑定的对象,参数列表]

                            return function () {

                                var args = Array.prototype.slice.call(arguments);

            -->这里的arguments与外面的不是同一个,这个是被代理的函数内部的arguments对象,

           比如这里的move函数的  arguments[0]=[object Event]就是这个事件内部的e参数

                                Array.prototype.unshift.apply(args, privateArgs);

           -->这里在加上传进来的参数,就实现了,和原生bind一样的参数形式

         //->而且这里是把私有的参数放到前面的比如a=new Mouse();a.move(1,2);

          //如果这个move方法没有参数,意思就是prototype.move=fn(){arguments} ,

          //而我传进来了参数,参数的arguments.length=3,

           //arguments[0]=1,arguments[1]=2,arguments[2]=[object event].

                                return fn.apply(target, args);

                            }

                    //这里之所以搞复杂了,是因为,在被代理的函数可以直接访问arguments,比如我不给被代理的函数传参数,而直接使用

                     //这样这个arguments就会包含与原生Function.prototype.bind的arguments一样的对象,

                     //这里代码深奥,是因为你没理解这里原生的bind里面的arguments是什么,知道了,就知道为什么绑定我自己的arguments

                    //做这么多,主要目的就是使你被代理的函数内部的arguments与function.prototype.bind里的arguments对象包含的东西一致

                        }

                 

                        return function () {

                            return fn.apply(target, arguments);

                        }

                    }

                    return proxy.apply(null, arguments);

                };

                /*支持原生的使用原生的*/

                Function.prototype.bind = Function.prototype.bind ||

        function (target) {                   //这里的this指代要被代理的函数

            if (1 < arguments.length) {

                var args = Array.prototype.slice.call(arguments, 1);  //取出参数列表

                args.unshift(this, target);  //这个args最终变成了[this,绑定的对象,参数列表]

                return proxy.apply(null, args);

        -->估计大家会跟17楼犯一样的错误,这里之所以这么复杂的操作arguments对象,只是为了能保证传进proxy函数中,保证arguments对象不失效

            }

            return proxy(this, target);

        };

            })();

    以上代码为什么我要一直return回来代理,因为这样你才能这样调用this.move.bind(this,1,2)()然后这里会立即执行函数!

    有了以上代码,我们就可以轻松的实现了"?"号这里要写什么代码了,^_^,简单吧

     if (document.addEventListener) {

                    document.addEventListener('mousemove', this.move.bind(this,1,2));

                } else if (document.attachEvent) {

                    document.attachEvent("onmousemove", this.move.bind(this,1,2));

                }

     是不是以后凡是碰到要添加事件,然后调用的方法的this又想指向其他对象,这样是不是很简单呢..

    看到大家对以上代码有点难理解,来个简单点得

     var a = function () {

                console.log(arguments[0]);   //1

                console.log(arguments[1]);   //2

                console.log(this.key1);

                //这样绑定参数的话,我的参数列出来才能和原生的bind一样,就这么简单,

            };

            var b = {

                key1: "value1"

            };

         a.bind(b, 1, 2)();

    反驳17楼同学的代码错误,我想这是很多人会犯的错误,代码如下

          Function.prototype.bind = function (target) {

                var self = this;

                return function () {

                    return self.apply(target, arguments); //这里的arguments根本传不进来

                }

            }

              var a = function () {

                  console.log(arguments.length);  //这样bind的话,arguments参数失效

                                                 //arguments.length=0.

                  console.log(this.key1);

              };

            var b = {

                        key1: "value1"

              };

                    a.bind(b, [1, 2], 3)();    //从这里可以看出,期望的arguments.length=2

                    //这也是我为什么苦口婆心的操作arguments参数

            //我知道这里大部分人都会觉得对的,但是你错了,17楼的同学你还得在思考下

    不带注释的源码,

         (function () {

                var proxy = function (fn, target) {

                    var proxy = function () {

                        if (2 < arguments.length) {

                            var privateArgs = Array.prototype.slice.call(arguments, 2);

                            return function () {

                                var args = Array.prototype.slice.call(arguments);

                                Array.prototype.unshift.apply(args,privateArgs);

                                return fn.apply(target, args);

                            }

                        }

                        return function () {

                            return fn.apply(target, arguments);

                        }

                    }

                    return proxy.apply(null, arguments);

                };

                /*支持原生的使用原生的*/

                Function.prototype.bind = Function.prototype.bind ||

        function (target) {               

            if (1 < arguments.length) {

                var args = Array.prototype.slice.call(arguments, 1);

                args.unshift(this, target); 

                return proxy.apply(null, args);

            }

            return proxy(this, target);

        };

            })();

  • 相关阅读:
    re模块 与正则表达式之间的关系 一.....
    计算机硬件组成
    随便
    linux crontab定时
    linux shell命令记录
    tomcat意外退出 A valid shutdown command was received via the shutdown port. Stopping the Server instance
    mongodb设置用户
    mongodb的mongo.conf文件 启动参数
    mysql设置不区分表名大小写
    mongodb报Write failed with error code 17280 and error message 'WiredTigerIndex::insert: key too large
  • 原文地址:https://www.cnblogs.com/uh-huh/p/4308527.html
Copyright © 2011-2022 走看看