`

javascript的 this 详解以及apply与call的用法意义及区别

 
阅读更多
JAVASCRIPT THIS详解:http://www.cnblogs.com/felix2007/archive/2007/03/21/682670.html
你不知道的 JavaScript - “this”:http://www.cnblogs.com/ruxpinsp1/archive/2008/04/20/1162463.html
关于JavaScript中apply与call的用法意义及区别
http://www.cnitblog.com/yemoo/archive/2007/11/30/37070.aspx


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

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

    1、在HTML元素事件属性中inline方式使用this关键字:
 <div onclick="
 // 可以在里面使用this

 ">division element</div>


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

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

<div id="elmtDiv">division element</div>
 <script language="javascript">
 var div = document.getElementById('elmtDiv');
 div.attachEvent('onclick', EventHandler);

 function EventHandler()
 {
    // 在此使用this
 }
 </script>


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

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

 <div id="elmtDiv">division element</div>
 <script language="javascript">
 var div = document.getElementById('elmtDiv');
 div.onclick = function()
 {
    // 在此使用this
 };
 </script>


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

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

  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关键字:

  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关键字使用:

  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关键字:

  <table width="100" height="100">
      <tr>
          <td>
              <div style="width: expression(this.parentElement.width); 
                    height: expression(this.parentElement.height);">
                  division element</div>
          </td>
      </tr>
  </table>


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

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

  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”
http://www.cnblogs.com/ruxpinsp1/archive/2008/04/20/1162463.html
JavaScript 里的 this 到底指得是什么?很多人都会告诉你 this 指的是当前对象。这样理解对么?在大多数情况下确实没错。比如我们经常会在网页上写这样的 JavaScript:

<input type="submit" value="提交" onclick="this.value='正在提交数据'" />

这里的this显然指的是当前对象,即这个提交按钮。通常,我们使用this的情况都与此类似。但是有什么情况不是这样的呢?

大家看看这个例子:
var foo = function() {
    console.log(this);
}
foo();
new foo();

比较一下 foo() 和 new foo() 的运行结果,你会发现,前者 this 指向的并非 foo 本身,而是当前页面的window对象,而后者才真正的指向foo。这是为什么呢?

其实这牵涉到JavaScript的一条重要特性,就是所谓的“闭包”。闭包这个概念说复杂也不复杂,但也不是简单到能用一两句话说清。偶会在以后的文章中深入探讨这个Javascript 最重要的特性。现在,我要告诉大家的是,因为闭包的存在,JavaScript中的作用域变得相当重要。

所谓的作用域,简单的说,就是创建一个函数时在什么环境下创建的。而this变量的值,如果没有指定的话,就是函数当前的作用域。


在前面的例子里,foo() 函数是在全局作用域(这里就是window对象),所以this的值是当前的window对象。而通过 new foo() 这样的形式,其实是创建了一个foo()的副本,并在这个副本上进行的操作,所以这里的this就是foo()的这个副本。


这样讲可能有点抽象,大家来看个实际的例子:
<input type="button" id="aButton" value="demo" onclick="" />
<script type="text/javascript">
function demo() {
    this.value = Math.random();
}
</script>

如果直接调用demo() 函数,程序就会报错,因为demo函数是在window对象中定义的,所以demo的拥有者(作用域)是window,demo的this也是window。而window是没有value属性的,所以就报错了。


如果我们通过创建副本的方式,将这个函数的副本添加到一个HTML元素,那么他的所有者就成了这个元素,this也指代了这个元素:
document.getElementById("aButton").onclick = demo;

这样就将aButton的onlick属性设置为demo()的一个副本,this也指向了aButton。

你甚至可以为多个不同的HTML元素创建不同的函数副本。每个副本的拥有者都是相对应的HTML元素,各自的this也都指向他们的拥有者,不会造成混乱。

但是,如果你这样定义某个元素的onlick事件:
<input type="button" id="aButton" value="demo" onclick="demo()" />

点击这个button之后,你会发现,程序又会报错了——this又指向了window!

其实,这种方法并没有为程序创建一个函数,而只是引用了这个函数。

具体看一下区别吧。
使用创建函数副本的方法:
<input type="button" id="aButton" value="demo" />
<script type="text/javascript">
var button = document.getElementById("aButton");
function demo() {
    this.value = Math.random();
}
button.onclick= demo;
alert(button.onclick);
</script>



得到的输出是:
function demo() {
    this.value = Math.random();
}



使用函数引用的方法:
<input type="button" id="aButton" value="demo" onclick="demo()" />
<script type="text/javascript">
var button = document.getElementById("aButton");
function demo() {
    this.value = Math.random();
}
alert(button.onclick);
</script>


得到的输出是:
function onclick() {
    demo();
}


这样就能看出区别了吧。函数引用的方式中,onclick事件只是直接调用demo()函数,而demo()函数的作用域仍旧是window对象,所以this仍然指向window。

这样就又引出了一个问题:既然函数副本这么好用,为什么还需要函数引用的方法呢?答案是性能。每新建一个函数的副本,程序就会为这个函数副本分配一定的内存。而实际应用中,大多数函数并不一定会被调用,于是这部分内存就被白白浪费了。而使用函数引用的方式,程序就只会给函数的本体分配内存,而引用只分配指针,这样效率就高很多。程序员么,节约为主,恩

所以我们来看一个更好的解决方案:
<script type="text/javascript">
function demo(obj) {
    obj.value = Math.random();
}
</script>
<input type="button" value="demo" onclick="demo(this)" />
<input type="button" value="demo" onclick="demo(this)" />
<input type="button" value="demo" onclick="demo(this)" />


这样,效率和需求就都能兼顾了。


最后再多讲一句:在前面的文章里,我特别强调了“如果没有指定this的话”。其实this是可以指定的。Function对象有两个方法:call()和apply()。这两个方法都支持指定一个函数中的this。有兴趣的话您可以去查一下Javascript的手册,看看这两个函数都是干什么用的。而我们经常用的 new foo() 可以用以下这段伪代码来描述:
function new (somefunction) {
    var args = [].slice.call(arguments, 1);
    somefunction.prototype.constructor = somefunction;
    somefunction.apply(somefunction.prototype, args);
    return somefunction.prototype;
}


现在明白了,在本文开头的第一个例子里,new foo() 的 this 为什么是 foo 了吧.




关于JavaScript中apply与call的用法意义及区别
http://www.cnitblog.com/yemoo/archive/2007/11/30/37070.aspx
JavaScript中有一个call和apply方法,其作用基本相同,但也有略微的区别。

先来看看JS手册中对call的解释:

call 方法
调用一个对象的一个方法,以另一个对象替换当前对象。

call([thisObj[,arg1[, arg2[,   [,.argN]]]]])

参数
thisObj
可选项。将被用作当前对象的对象。

arg1, arg2,  , argN
可选项。将被传递方法参数序列。

说明
call 方法可以用来代替另一个对象调用一个方法。call 方法可将一个函数的对象上下文从初始的上下文改变为由 thisObj 指定的新对象。

如果没有提供 thisObj 参数,那么 Global 对象被用作 thisObj。

说明白一点其实就是更改对象的内部指针,即改变对象的this指向的内容。这在面向对象的js编程过程中有时是很有用的。

引用网上一个代码段,运行后自然就明白其道理。

<input type="text" id="myText"   value="input text">
<script>
    function Obj(){this.value="对象!";}
    var value="global 变量";
    function Fun1(){alert(this.value);}

    window.Fun1();   //global 变量, 默认window赋值给方法里面的this
    Fun1.call(window);  //global 变量, 调用方法,并把方法里面的this指向window这个参数
    Fun1.call(document.getElementById('myText'));  //input text, 调用方法,并把方法里面的this指向document.getElementById('myText')这个参数
    Fun1.call(new Obj());   //对象!, 调用方法,并把方法里面的this指向new Obj()这个参数
</script>


call函数和apply方法的第一个参数都是要传入给当前对象的对象,及函数内部的this。后面的参数都是传递给当前对象的参数。
运行如下代码:
<script>
   var func=new function(){this.a="func"}
    var myfunc=function(x){
        var a="myfunc";
        alert(this.a);
        alert(x);
    }
    myfunc.call(func,"var");
</script>


可见分别弹出了func和var。到这里就对call的每个参数的意义有所了解了。

对于apply和call两者在作用上是相同的,但两者在参数上有区别的。
对于第一个参数意义都一样,但对第二个参数:
apply传入的是一个参数数组,也就是将多个参数组合成为一个数组传入,而call则作为call的参数传入(从第二个参数开始)。

如 func.call(func1,var1,var2,var3)对应的apply写法为:func.apply(func1,[var1,var2,var3])

同时使用apply的好处是可以直接将当前函数的arguments对象作为apply的第二个参数传入
分享到:
评论

相关推荐

    javascript技术难点(三)之this、new、apply和call详解

    JavaScript中的this、new、apply和call是理解JavaScript面向对象编程的关键知识点。首先,我们要知道,this关键字在...因此,深入理解this、new、apply和call的原理和使用方法,对于提升JavaScript编程能力至关重要。

    js中apply与call简单用法详解.docx

    ### JavaScript中的apply与call用法详解 #### 一、引言 在JavaScript中,`apply`与`call`是两个非常重要的函数,它们都属于`Function.prototype`的一部分,因此每一个函数对象都拥有这两个方法。这两个方法的主要...

    JavaScript中this关键字使用方法详解

    在本文中,我们将深入探讨`this`在JavaScript中的工作原理,以及在不同场景下的用法。 1. **函数调用方式** 在函数调用中,`this`的值取决于函数被调用的方式。如果函数是作为对象的方法调用,`this`将指向调用该...

    JavaScript中的apply和call函数详解_.docx

    在JavaScript中,`apply`和`call`是两种非常重要的函数调用方式,它们都用于改变函数内部`this`的指向以及动态传递参数。这两者的主要区别在于参数的传递方式。 首先,`this`在JavaScript中是一个关键字,它在不同...

    详解js中的apply与call的用法.docx

    在JavaScript中,`call`和`apply`是两种非常重要的函数调用方式,它们都用于改变函数执行时的上下文,即改变`this`的指向。这两个方法的主要区别在于它们处理参数的方式。 `call`方法允许你指定一个对象来替代原...

    【JavaScript源代码】JavaScript函数之call、apply以及bind方法案例详解.docx

    JavaScript中的call、apply和bind方法都是用来改变函数调用时的上下文(即this值)以及传递参数。它们之间的相同点在于,都能够指定函数执行时的this对象,并且都能接收参数。不同点在于它们的调用方式和执行时机。 ...

    JavaScript中的this,call,apply使用及区别详解

    在深入探讨JavaScript中this关键字、call和apply方法之前,先来简单回顾一下JavaScript的基本特性。JavaScript是一种基于原型的脚本语言,它运行在浏览器和服务器环境中,常用于开发网页和Web应用程序。其中,this...

    Javascript中call,apply,bind方法的详解与总结

    本文针对JavaScript中三个重要的函数方法——call、apply和bind,进行详尽的分析,并在文章的结尾部分对这三个方法之间的联系和区别进行了概括,以便于读者更深入地理解它们的用途和应用场景。 首先,我们来探讨...

    Javascript的this详解

    3. **显式绑定**:通过`call`、`apply`或`bind`方法,我们可以显式地设置`this`的值。这些方法允许我们指定一个对象,使得函数在执行时`this`指向该对象。例如: ```javascript function foo() { console.log...

    详解js中call与apply关键字的作用.docx

    JavaScript中的`call`和`apply`是两种非常重要的方法,它们都用于改变函数内部`this`的指向,并执行该函数。这两个方法都是Function对象的原型方法,因此所有的函数都具备`call`和`apply`。 1. `call`方法: - `...

    浅谈javascript中的call、apply、bind_.docx

    JavaScript 中的 call、apply、bind 方法详解 JavaScript 中的 call、apply、bind 方法是 Function 对象自带的三个方法,这三个方法的主要作用是转变函数中的 this 指向,从而可以达到“接花移木”的效果。下面将对...

    JS中的call、apply、bind方法详解.pdf

    JS中的call、apply、bind方法详解 随着JavaScript的发展,函数调用对象的改变变得越来越重要。在JavaScript中,call、apply、bind三个方法都是函数对象的方法,它们的作用都是改变函数的调用对象。下面,我们将详细...

    详解JavaScript函数callee、call、apply的区别

    `apply`方法与`call`类似,也是改变`this`值并立即执行函数,但它的区别在于接收参数的方式。`apply`的第一个参数也是设置`this`的值,第二个参数是一个数组或类数组对象,它的元素将作为参数传递给函数。例如: ``...

    JavaScript中的apply和call函数详解

    在JavaScript中,apply和call是两个非常重要的函数,它们允许开发者在调用函数时指定函数体内this的值。了解apply和call的用法对于深入掌握JavaScript编程是非常有帮助的。首先,我们需要明白在JavaScript中,函数也...

    详解JavaScript中this关键字的用法_.docx

    `call()`和`apply()`方法允许我们改变函数执行时的`this`值。它们的主要区别在于传递参数的方式。 - `call()`方法接受一个`this`值和一组参数,参数列表是直接传递的。 - `apply()`方法接受一个`this`值和一个...

    Javascript的this用法

    ### JavaScript中的`this`用法详解 在JavaScript中,`this`关键字的使用十分常见,但也是最容易引起混淆的部分之一。正确理解`this`的工作原理对于编写高效、可靠的代码至关重要。本文将深入探讨`this`在不同上下...

    【JavaScript源代码】JavaScript函数this指向问题详解.docx

    在本文中,我们将深入探讨`this`在各种函数调用场景下的行为,并介绍如何通过`call`、`apply`和`bind`方法改变函数内部`this`的指向。 ### 一、函数内`this`的指向 1. **普通函数**:在全局作用域或非严格模式下,...

    高手详解javascript中的this指针

    使用`call()`, `apply()`, 或 `bind()`方法可以显式地设置`this`的值。这些方法允许开发者在调用函数时指定`this`的指向,这对于模拟类的行为或者在不兼容的环境中实现某些功能非常有用。 5. **箭头函数中的`this`...

Global site tag (gtag.js) - Google Analytics