Javascript中的this,call,apply,bind!

    技术2022-05-19  19

    今天无意间在这里看到一篇说js中this的文章,看后满是疑问。。。

      作者试用this.xXP作windowsroperty取某些属性得到了undefined等一系列非意料中的结果

      于是认为导致这种情况是因为之前有过对this.propertyX赋值从而改变了this所至。。。

      好吧...

      一: this

      看这个源代码

       0. <script>     1. function test(){     2. alert(this.location); //这里的this是window,你可以取到任何window的属性但别妄想取button的属性     3. }     4. </script><input οnclick="test();" value="click1" type="button">  

      当然要取到button dom node的信息也是十分简单的

       0. <input οnclick="test(this);" value="click1" type="button"> 

      如上源代码,传过去this,当做参数处理即可

      当然也有别的看似更体面的办法

       0. <script>     1. function test_handler(){     2. //这里的this就不再是window了,而是我们要的button了,其实就是addHandler中所定义的事件发生体     3. //当然也只有等你所定义的事件(这里是onclick)触发后才有instance     4. alert(this.id);      5. }     6. function addHandler(){     7. document.getElementById("button1").onclick = test_handler;     8. }     9. window.onload = addHandler;    10. </script><input id="button1" value="click1" type="button">  但是不得不承认由this引起的错误源代码还是会很容易就进来

      看下面的源代码

       0. <script>     1. function test_handler(par){     2. this.par = par;     3. this.output = function(){     4. alert(this.par);     5. }     6. }     7. function addHandler(){     8. var obj = new test_handler("my paramters input");     9. document.getElementById("button1").onclick = obj.output;    10. }    11. window.onload = addHandler;    12. </script><input id="button1" value="click1" type="button">  

      很容易写出这样的源代码。。。我们期望的结果肯定是alert出来my paramters input,但是实际上却是undefined

      其实这里的错误就是最上面2种情况的综合,这里alert(this.par);中的this是button而不再是test_handler的instance了

      2, call

      先看一个最简单的例子

       0. <script>     1. var first_json = {     2. first: 20     3. };     4. var first_obj = function(first){     5. this.first = first;     6. }     7. var obj = new first_obj(100);     8. function Calculate(secondNum){     9. return this.first * secondNum;    10. }    11. document.writeln(Calculate.call(1, 5)); //NaN: Not a number    12. document.writeln(Calculate.call({first:10}, 5)); //50    13. document.writeln(Calculate.call(first_json, 5)); //100    14. document.writeln(Calculate.call(obj, 5)); //500    15. </script>NaN    16. 50    17. 100    18. 500  NaN50100500

    上面有4次call,其中理解Calculate办法中的this是得出正确答案的关键

      第一次:this是1,this.first = undefined 作乘法运算当然得出NaN

      第二次:this是{first:10}

      第三次:.....

      其实可以看出这里试用了call后我们可以轻而易举的改变this的内容,那么是否能想到在上面第一部分this的试用时某些时候用call来调用就可以避免我犯那些由于没搞清楚this是什么而导致的错误?答案是肯定的,但是先看下apply

      3, apply

      其实这个跟call类似,更改下刚才call中源代码,如果我们要计算3个数而不是2个数的积怎么办?

       0. <script>     1. var first_json = {     2. first: 20     3. };     4. var first_obj = function(first){     5. this.first = first;     6. }     7. var obj = new first_obj(100);     8. function Calculate(){     9. var result = this.first;    10. for(var i = 0; i < arguments.length; i++){    11. result = result * arguments[i];    12. }    13. return result;    14. }    15. document.writeln(Calculate.apply(1, [5, 5])); //NaN: Not a number    16. document.writeln(Calculate.apply({first:10}, [5, 5])); //50 * 5    17. document.writeln(Calculate.apply(first_json, [5, 5])); //100 * 5    18. document.writeln(Calculate.apply(obj, [5, 5])); //500 * 5    19. document.writeln(Calculate.call(obj, [5, 5])); //NaN: Not a number    20. </script>NaN    21. 250    22. 500    23. 2500    24. NaN  NaN2505002500NaN

    恩,apply的第二个参数是数组,这是call不容易做到的

      4, bind

      好,有了call和apply,现在试图来更改第一部分中的源代码, 我为了避免混淆this内容,所以我要显示的在call的第一个参数里传我的this过去

      看一下源代码

       0. <script>     1. function test_handler(par){     2. this.par = par;     3. this.output = function(){     4. alert(this.par);     5. }     6. }     7. function addHandler(){     8. var obj = new test_handler("my paramters input");     9. document.getElementById("button1").onclick = obj.output.call(obj);//this => var obj = new test_handler("my paramters input")    10. }    11. window.onload = addHandler;    12. </script><input id="button1" value="click1" type="button">  

      问题又出现了,instance是传过去了,也可以alert出来我想要的东西了,但是我得再window load的时候加载addHandler啊,这样直接call了就导致我页面load的时候就直接执行了我的函数,直接alert信息出来了,这还不止,还有个js错误。。。

      似乎到这里就联想不下去了,不知道怎么处理了。。。于是又来一个新办法bind

      说简单点bind的性能就是拿一个instance绑定到一个method,那么显然这个bind生效后method内部的this也就全成了之前绑定时的那个instance了,也就不存在混不混了

      时间不早了,直接看下更改完成的源代码吧

       0. <script>     1. function test_handler(par){     2. this.par = par;     3. this.output = function(){     4. alert(this.par);     5. alert(this.id);     6. }     7. }     8. Function.prototype.bind = function(instance){     9. var method_self = this;    10. temp = function(){    11. return method_self.apply(instance, arguments);    12. };    13. return temp;    14. }    15. function addHandler(){    16. var obj = new test_handler("my paramters input");    17. var btn = document.getElementById("button1");    18. btn.onclick = obj.output.bind(obj); //my paramters input; undefined    19. //btn.onclick = obj.output.bind(btn); //undefined; button1    20. }    21. window.onload = addHandler;    22. </script><input id="button1" value="click1" type="button">  

      注意看下上面源代码中的注释为分别2种情况下的2次alert结果,完全符合意料,通过bind我们简单实现了显示传递instance

    本文来自博客,转载请标明出处:http://blog.csdn.net/iadozhao/archive/2010/03/30/5430466.aspx


    最新回复(0)