this应用

 1. 不像C#,this一定是指向当前对象。

js的this指向是不确定的,也就是说是可以动态改变的。call/apply 就是用于改变this指向的函数,这样设计可以让代码更加灵活,复用性更高。

   2. this 一般情况下,都是指向函数的拥有者。

这一点很重要!这一点很重要!这一点很重要!

   这也是一道常见的面试题,如下代码:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<script type= "text/javascript" >
   var number = 1;
   var obj = {
      number: 2,
     showNumber: function (){
        this .number = 3;
       ( function (){         
         console.log( this .number);
       })();
       console.log( this .number);
     }
  };
  obj.showNumber();
</script>

  由于showNumber方法的拥有者是obj,所以this.number=3; this 指向的就是 obj 的属性 number。

  同理,第二个 console.log 打印的也是属性 number。

   为什么第二点说一般情况下this都是指向函数的拥有者,因为有特殊情况。函数自执行就是特殊情况,在函数自执行里,this 指向的是:window。所以第一个 console.log 打印的是 window 的属性 number。

   所以要加一点:

   3. 在函数自执行里,this 指向的是 window 对象。

   扩展,关于this,还有一个地方比较让人模糊的是在 dom 事件里,通常有如下3种情况:

   如下:

   1. 使用标签属性注册事件,此时this 指向的是 window 对象。

?
1
2
<input id= "test" type= "button" value= "按钮" onClick= "test()" />
   function test(){alert( this )}

   2. 对于1,要让 this 指向 input,可以将 this 作为参数传递。

   3. 使用 addEventListener 等注册。此时this 也是指向 input。

?
1
document.getElementById( "test" ).addEventListener( "click" ,test);

   在面向对象编程语言中,对于this关键字我们是非常熟悉的。比如C++、C#和Java等都提供了这个关键字,虽然在开始学习的时候觉得比较难,但只要理解了,用起来是非常方便和意义确定的。JavaScript也提供了这个this关键字,不过用起来就比经典OO语言中要"混乱"的多了。

  下面就来看看,在JavaScript中各种this的使用方法有什么混乱之处?

  1、在HTML元素事件属性中inline方式使用this关键字:

?
1
2
3
4
// 可以在里面使用this 
">division element
  // 可以在里面使用this
  " >division element

我们一般比较常用的方法是在此使用:javascirpt: EventHandler(this),这样的形式。不过这里其实可以写任何合法的JavaScript语句,要是高兴在此定义个类也可以(不过将会是个内部类)。这里的原理是脚本引擎生成了一个div实例对象的匿名成员方法,而onclick指向这个方法。

   2、用DOM方式在事件处理函数中使用this关键字:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
division element
 
  var div = document.getElementById( 'elmtDiv' ); 
  div.attachEvent( 'onclick' , EventHandler); 
  
  function EventHandler() 
 
  // 在此使用this 
 
   
// -->
  
division element
 
  var div = document.getElementById( 'elmtDiv' );
  div.attachEvent( 'onclick' , EventHandler);
 
  function EventHandler()
  {
  // 在此使用this
  }
  
// -->

  这时的EventHandler()方法中的this关键字,指示的对象是IE的window对象。这是因为EventHandler只是一个普通的函数,对于attachEvent后,脚本引擎对它的调用和div对象本身没有任何的关系。同时你可以再看看EventHandler的caller属性,它是等于null的。如果我们要在这个方法中获得div对象引用,应该使用:this.event.srcElement。

  3、用DHTML方式在事件处理函数中使用this关键字:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
division element
   
lt;mce:script language= "javascript" >
var div = document.getElementById( 'elmtDiv' ); 
div.onclick = function () 
  // 在此使用this 
}; 
  
/ -->
  
division element
 
  var div = document.getElementById( 'elmtDiv' );
  div.onclick = function ()
  {
  // 在此使用this
  };
  
// -->

  这里的this关键字指示的内容是div元素对象实例,在脚本中使用DHTML方式直接为div.onclick赋值一个EventHandler的方法,等于为div对象实例添加一个成员方法。这种方式和第一种方法的区别是,第一种方法是使用HTML方式,而这里是DHTML方式,后者脚本解析引擎不会再生成匿名方法。

  4、类定义中使用this关键字:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
function JSClass() 
var myName = 'jsclass'
this .m_Name = 'JSClass'
  
JSClass.prototype.ToString = function () 
alert(myName + ', ' + this .m_Name); 
}; 
  
var jc = new JSClass(); 
jc.ToString();
  function JSClass()
  {
  var myName = 'jsclass' ;
  this .m_Name = 'JSClass' ;
  }
 
  JSClass.prototype.ToString = function ()
  {
  alert(myName + ', ' + this .m_Name);
  };
 
  var jc = new JSClass();
  jc.ToString();

  这是JavaScript模拟类定义中对this的使用,这个和其它的OO语言中的情况非常的相识。但是这里要求成员属性和方法必须使用this关键字来引用,运行上面的程序会被告知myName未定义。

5、为脚本引擎内部对象添加原形方法中的this关键字:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function .prototype.GetName = function () 
var fnName = this .toString(); 
fnName = fnName.substr(0, fnName.indexOf( '(' )); 
fnName = fnName.replace(/^ function /, '' ); 
return fnName.replace(/(^\s+)|(\s+$)/g, '' ); 
function foo(){} 
alert(foo.GetName()); 
  function .prototype.GetName = function ()
  {
  var fnName = this .toString();
  fnName = fnName.substr(0, fnName.indexOf( '(' ));
  fnName = fnName.replace(/^ function /, '' );
  return fnName.replace(/(^\s+)|(\s+$)/g, '' );
  }
  function foo(){}
  alert(foo.GetName());

  这里的this指代的是被添加原形的类的实例,和4中类定义有些相似,没有什么太特别的地方。

  6、结合2&4,说一个比较迷惑的this关键字使用:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
view plaincopy to clipboardprint?
function JSClass() 
this .m_Text = 'division element'
this .m_Element = document.createElement( 'DIV' ); 
this .m_Element.innerHTML = this .m_Text; 
   
this .m_Element.attachEvent( 'onclick' , this .ToString); 
   
JSClass.prototype.Render = function () 
document.body.appendChild( this .m_Element); 
}  
  
JSClass.prototype.ToString = function () 
alert( this .m_Text); 
}; 
  
var jc = new JSClass(); 
jc.Render(); 
jc.ToString();
  function JSClass()
  {
  this .m_Text = 'division element' ;
  this .m_Element = document.createElement( 'DIV' );
  this .m_Element.innerHTML = this .m_Text;
   
  this .m_Element.attachEvent( 'onclick' , this .ToString);
  }
   
  JSClass.prototype.Render = function ()
  {
  document.body.appendChild( this .m_Element);
  }
 
  JSClass.prototype.ToString = function ()
  {
  alert( this .m_Text);
  };
 
  var jc = new JSClass();
  jc.Render();
  jc.ToString();

  我就说说结果,页面运行后会显示:"division element",确定后点击文字"division element",将会显示:"undefined"。

  7、CSS的expression表达式中使用this关键字:

?
1
2
3
4
5
height: expression( this .parentElement.height); "> 
  division element 
   
  height: expression(this.parentElement.height);" >
  division element

这里的this看作和1中的一样就可以了,它也是指代div元素对象实例本身。

  8、函数中的内部函数中使用this关键字:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
view plaincopy to clipboardprint?
function OuterFoo() 
this .Name = 'Outer Name'
  
function InnerFoo() 
var Name = 'Inner Name'
alert(Name + ', ' + this .Name); 
return InnerFoo; 
OuterFoo()();
  function OuterFoo()
  {
  this .Name = 'Outer Name' ;
  
  function InnerFoo()
  {
  var Name = 'Inner Name' ;
  alert(Name + ', ' + this .Name);
  }
  return InnerFoo;
  }
  OuterFoo()();

  运行结果显示是:"Inner Name, Outer Name"。按我们在2中的讲解,这里的结果如果是"Inner Name, undefined"似乎更合理些吧?但是正确的结果确实是前者,这是由于JavaScript变量作用域的问题决定的,详细了解推荐参看"原来JScript中的关键字'var'还是有文章的"一文及回复。

    归纳起来,JavaScript中的this用法有以下3种(详细用法参原文):

    1.在HTML元素事件属性 或 CSS的expression表达式 中inline方式使用this关键字——对应原文的1、7

    2.在事件处理函数中使用this关键字——对应原文的2、3

      其中可分为两种方式

      (1)DOM方式——此种方式的结果是this指向窗口(window)对象

      (2)DHTML方式——此种方式的结果是this指向div元素对象实例

    3.在类定义中使用this关键字并在其 内部函数 或 成员函数(主要是prototype产生)中使用——对应原文的4、5、8

      需要说明的是,在函数也是个对象,因此需要区分 变量定义 和 成员变量定义,如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
view plaincopy to clipboardprint?
 
var variableName;    //变量定义 
//作用域:函数定义范围内 
//使用方法:直接使用variableName 
this .varName;      //成员变量定义 
//作用域:函数对象定义范围内及其成员函数中 
//使用方法:this.varName
var variableName;    //变量定义
//作用域:函数定义范围内
//使用方法:直接使用variableName
this .varName;      //成员变量定义
//作用域:函数对象定义范围内及其成员函数中
//使用方法:this.varName

 以上归纳出的三类this的使用方法中,第一种比较容易理解,这里对原文中第6点提到的程序进行了测试和改进如下,以说明上述后两种使用方法:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
view plaincopy to clipboardprint?
 
     function JSClass() 
    
       var varText = "func variable!" ;                 //函数中的普通变量 
       this .m_Text = 'func member!' ;                    //函数类的成员变量 
       this .m_Element = document.createElement( 'DIV' );   //成员变量,创建一个div对象 
       this .m_Element.innerHTML = varText;             //使用函数的普通变量 
       this .m_Element.attachEvent( 'onclick' , this .ToString);  //给这个对象的事件连上处理函数 
       this .newElement = document.createElement( 'DIV' ); 
       this .newElement.innerHTML = "new element" ;  
       this .newElement.m_Text = "new element text!" ;      //给创建的对象建个成员 
       this .newElement.onclick = function () 
      
         alert( this .m_Text);                       //指向div对象的成员 
       }; 
    
    
     JSClass.prototype.Render = function () 
    
       document.body.appendChild( this .m_Element);       //把div对象挂在窗口上 
       document.body.appendChild( this .newElement); 
     }   
  
     JSClass.prototype.ToString = function () 
    
       alert( this .m_Text);                         //指向窗口(window)对象 
     }; 
  
     function initialize(){ 
       var jc = new JSClass(); 
       jc.Render(); 
       jc.ToString();                             //里面的this指向JSClass类的实例,里面有m_Text成员 
    
     
// --> 
 
     initialize(); 
     
// --> 
   
  function JSClass()
   {
    var varText = "func variable!" ;     //函数中的普通变量
     this .m_Text = 'func member!' ;     //函数类的成员变量
     this .m_Element = document.createElement( 'DIV' ); //成员变量,创建一个div对象
     this .m_Element.innerHTML = varText;    //使用函数的普通变量
     this .m_Element.attachEvent( 'onclick' , this .ToString); //给这个对象的事件连上处理函数
     this .newElement = document.createElement( 'DIV' );
     this .newElement.innerHTML = "new element" ;
     this .newElement.m_Text = "new element text!" //给创建的对象建个成员
     this .newElement.onclick = function ()
    {
      alert( this .m_Text);      //指向div对象的成员
    };
   }
   
   JSClass.prototype.Render = function ()
   {
     document.body.appendChild( this .m_Element);  //把div对象挂在窗口上
     document.body.appendChild( this .newElement);
   }  
 
   JSClass.prototype.ToString = function ()
   {
     alert( this .m_Text);       //指向窗口(window)对象
   };
 
  function initialize(){
    var jc = new JSClass();
    jc.Render();
    jc.ToString();        //里面的this指向JSClass类的实例,里面有m_Text成员
   }
   
// -->
 
    initialize();
   
// -->

上面的代码执行结果是:

页面加载时,弹出对话框,输出func member!

页面上显示

?
1
2
func variable!
new element

单击func variable时,弹出对话框,显示undefined

  ——因为这时toString函数里的this指针指向window

单击new element时,弹出对话框显示new element text!

  ——因为这时toString函数里的this指针指向div元素,而该元素已经定义了m_Text成员(this.newElement.m_Text = "new element text!")

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 C++ ,this 指针是一个隐含于每个非静态成员函数的指针,它指向调用该函数的对象。 下面是一个示例: ```cpp #include <iostream> class MyClass { public: void printAddress() { std::cout << "Address of this pointer: " << this << std::endl; } }; int main() { MyClass obj1, obj2; obj1.printAddress(); obj2.printAddress(); return 0; } ``` 输出: ``` Address of this pointer: 0x7fff5fbff6b7 Address of this pointer: 0x7fff5fbff6b6 ``` 在上面的示例,我们定义了一个名为 MyClass 的类,并在其定义了一个名为 printAddress 的成员函数,该函数输出 this 指针的地址。在 main 函数,我们创建了两个 MyClass 对象 obj1 和 obj2,并对它们都调用了 printAddress 函数。输出结果显示,这两个对象的 this 指针指向的地址是不同的,这是因为它们是不同的对象。 this 指针的应用非常广泛,其一个常见的用法是在成员函数返回对象本身的引用,即 `return *this;`。这在编写链式调用的代码时非常方便,例如: ```cpp class MyClass { public: MyClass& setValue(int value) { this->value = value; return *this; } MyClass& setName(const std::string& name) { this->name = name; return *this; } private: int value; std::string name; }; int main() { MyClass obj; obj.setValue(10).setName("example"); return 0; } ``` 在上面的示例,我们定义了两个成员函数 setValue 和 setName,它们都返回对象本身的引用,这样我们就可以使用链式调用来设置对象的值。在 main 函数,我们创建了一个 MyClass 对象 obj,并对它使用了两个成员函数。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值