this, Function.apply 及Function.call

来源:互联网 发布:tensorflow 预测结果 编辑:程序博客网 时间:2024/06/10 11:37
http://www.cnblogs.com/PengNian/articles/838215.html


考虑以下这段代码:

 1    <input type="button" id="btnSubmit" value="Click me!" />
 2
 3    <script language="javascript" type="text/javascript">
 4        function ButtonManager(buttonId, message)
 5        {
 6            this._message = message;
 7            document.getElementById(buttonId).onclick = this.ShowMessage;    
 8        }

 9        
10        ButtonManager.prototype.ShowMessage=function()
11        {
12            alert(this._message);
13        }

14        
15        var btnManager = new ButtonManager("btnSubmit""Hello!");
16    </script>


        按预想的意图,当点击按钮时,应当会弹出"Hello!",但上面的代码运行,却弹出"undefined"。问题出在哪里呢?在12行设个断点,对它进行调试,发现this竟然是指向btnSubmit,如果是这样的话,那就难怪会弹出"undefined",因为btnSubmit本身并没有定义_message,而我们所期望的this应当是指向btnManager,我们真正期望调用的方法其实是btnManager.ShowMessage()。
         
       事实上,这是与Javascript的语法和运行机制有关的,当ShowMessage真正调用前,this的指向是不明确,而只有在运行里,this的指向会由运行时来决定。

       那么有没有什么方法来正确实现上述意图呢?答案是肯定的,首先要可以看下面的代码:

1var x=10;
2var o ={x:15};
3function foo()
4{
5alert(this.x);
6}

7foo();
8foo.call(o);

    运行之后,我们会发现结果会分别是10和15。这似乎有点疑惑了,当然关键点肯定就是那个Call了。
Javascript中的function本身也是一个object,它本身就会有tostring(),call(),apply()几个附加方法。这个function.call的意义就在于,当调用时它时,运行时会把它的第一个参数替换掉function的this指向。
      当调用foo()时,this是指向window的,而事实上,所有的全局变量就是window的属性。foo.call(o)时,this是指向o的。
理解了function.call的作用,当解决上面的问题就不难了。

 1    <input type="button" id="btnSubmit" value="Click me!" />
 2
 3    <script language="javascript" type="text/javascript">
 4        function ButtonManager(buttonId, message)
 5        {
 6            this._message = message;
 7            document.getElementById(buttonId).onclick = createDelegate(this,this.ShowMessage);
 8        }

 9        
10        ButtonManager.prototype.ShowMessage=function()
11        {
12            alert(this._message);
13        }

14        
15        function createDelegate(object, method)
16        {
17            var delegate = function()
18                {
19                    method.call(object);
20                }

21             return delegate;
22        }

23        
24        var btn = new ButtonManager("btnSubmit""Hello!");
25
26    </script>


我们加入一个createDelegate的funciton,它的作用类似为onclick事件创建一个事件委托对象。现在,代码可以正常工作了。

另外,function.apply()和function.call()基本功能是一样的,但apply却可以授受两个参数,而且第二个参数必须是一个数组。

 1        var o = {x:10};
 2        function f(message)
 3        {
 4            alert(message+(this.x*this.x));
 5        }

 6        
 7        function g(object, func)
 8        {
 9            var args =[];
10            for(var i=2;i<arguments.length;i++)
11            {
12                args.push(arguments[i]);
13            }

14            func.apply(object,args);
15        }

16        
17        g(o,f,"result : ");


基于apply的这个特点,apply比call使用更加广泛,在javascript中的继承中,apply的使用也是必不可少的