這段js代碼得拯救你多少時間

來源:互聯網
上載者:User

 

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();

www.2cto.com

上面你知道'?'號那裡要幹嘛了嗎?我想給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);

    };

        })();

www.2cto.com

以上代碼為什麼我要一直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));

            }

www.2cto.com

 是不是以後凡是碰到要添加事件,然後調用的方法的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)();

www.2cto.com

 

反駁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);

    };

        })();

www.2cto.com

 

 

 

 

如若需要轉載本文,請附上連結

 

 

http://www.cnblogs.com/nothingbrother/

  

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.