javascript 的函数在执行期间才会确定他的context,也就是说this在此时被赋值。

但是你常常遇到这种情况

function process(){ 

 this.name = "hello"; 

  document.onclick = function(){    

alert(this.name); 

 }  

}

var  p = new process(); 

-------------------------------------

上面这个 程序执行之后,你在页面上“点击”,你期待出现的是 “hello”,实际的结果是 undefined;


1问题来了,this.name 怎么会没定义呢,  仔细看下发现 ,点击时,执行了函数 那么此时的context是什么呢,this 自然就是document,但是document没有name属性,自然就是没定义了。


2 你期待的结果是什么呢   弹出 “hello”

  怎么解决呢

  (1)既然执行函数时this赋值,我们不使用this 不就完了

function process(){

            var self = this;

            this.name = "hello";

  

            document.onclick = function(){

                alert(self.name);

            }

(2) 还想使用this     ES5 中使用了一个bind方法,可以实现这个

            document.onclick = function(){

                alert(this.name);

            }.bind(this);

但是这里有个问题,就是bind 函数只能针对 expression的函数声明,对于declaration的 没有此函数

并且并不是所有的浏览器都支持这个方法。

跨浏览器的做法

        Function.prototype.bind = Function.prototype.bind || function(th){

            var func = this;

            return function(){

                func.apply(th,[].slice.call(arguments));

            }

        }

(3) 还有一种方法,我们可以利用一个工具函数,专门的导入这个this,保持this的上下文一致

        function fixThis(func,th){

            return function(){

                return func.apply(th);           

            }

        }

上面的点击可以写成

            document.onclick = fixThis(function(){

                alert(this.name);

            },this);

----------------------------------------

早期绑定有个问题是,当你遇到继承的情况

        function preBind(func,th){

            return function(){

                func.apply(th,[].slice.call(arguments));

            }

        }

        function Animal(){

            this.type = function(){

                alert("Animal");

            }

          document.onclick = preBind(this.type,this); 

    

        }


        function Cat(){

            Animal.call(this);//继承 Animal

            this.type = function(){

                alert("cat");

            }

        }


//执行

new Cat();

你期待的结果是,点击之后,出现“cat”  但是实际的结果是 “Animal”,问题出在哪里呢

问题出在这里   document.onclick = preBind(this.type,this);      这个函数是在 Animal 里面注册的,

当 继承时,即执行preBind() 函数,返回一个闭包,此闭包的环境hold住的弹出内容的方法体是 “Animal"那个


如何解决呢,  把早期绑定的内容 换成,下面这个,后期绑定,执行时根据具体的环境决定那个函数被调用。

        function postBind(str,th){

            return function(){

                return th[str].apply(th,[].slice.call(arguments));

            }

        }