<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>简单生活 -- Kevin Yang的博客 &#187; 函数对象传参</title>
	<atom:link href="http://www.imkevinyang.com/tags/%e5%87%bd%e6%95%b0%e5%af%b9%e8%b1%a1%e4%bc%a0%e5%8f%82/feed" rel="self" type="application/rss+xml" />
	<link>http://www.imkevinyang.com</link>
	<description>It&#039;s all about sharing</description>
	<lastBuildDate>Sun, 05 Feb 2012 15:37:14 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>详解Javascript 中的this指针</title>
		<link>http://www.imkevinyang.com/2009/07/%e8%af%a6%e8%a7%a3javascript-%e4%b8%ad%e7%9a%84this%e6%8c%87%e9%92%88.html</link>
		<comments>http://www.imkevinyang.com/2009/07/%e8%af%a6%e8%a7%a3javascript-%e4%b8%ad%e7%9a%84this%e6%8c%87%e9%92%88.html#comments</comments>
		<pubDate>Sun, 05 Jul 2009 11:31:05 +0000</pubDate>
		<dc:creator>Kevin Yang</dc:creator>
				<category><![CDATA[Web传统技术]]></category>
		<category><![CDATA[技术随笔]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Javascript高级特性]]></category>
		<category><![CDATA[this指针]]></category>
		<category><![CDATA[函数对象传参]]></category>

		<guid isPermaLink="false">http://www.imkevinyang.com/2009/07/%e8%af%a6%e8%a7%a3javascript-%e4%b8%ad%e7%9a%84this%e6%8c%87%e9%92%88.html</guid>
		<description><![CDATA[前言
<p>Javascript是一门基于对象的动态语言，也就是说，所有东西都是对象，一个很典型的例子就是函数也被视为普通的对象。Javascript可以通过一定的设计模式来实现面向对象的编程，其中this “指针”就是实现面向对象的一个很重要的特性。但是this也是Javascript中一个非常容易理解错，&#8230;</p>]]></description>
			<content:encoded><![CDATA[<h2>前言</h2>
<p>Javascript是一门基于对象的动态语言，也就是说，所有东西都是对象，一个很典型的例子就是函数也被视为普通的对象。Javascript可以通过一定的设计模式来实现面向对象的编程，其中this “指针”就是实现面向对象的一个很重要的特性。但是this也是Javascript中一个非常容易理解错，进而用错的特性。特别是对于接触静态语言比较久了的同志来说更是如此。</p>
<h2>示例说明</h2>
<p>我们先来看一个最简单的示例：</p>
<pre class="csharpcode"><span class="kwrd">&lt;</span><span class="html">script</span> <span class="attr">type</span><span class="kwrd">=&quot;text/javascript&quot;</span><span class="kwrd">&gt;</span>
    <span class="kwrd">var</span> name = <span class="str">&quot;Kevin Yang&quot;</span>;
    <span class="kwrd">function</span> sayHi(){
       alert(<span class="str">&quot;你好，我的名字叫&quot;</span> + name);
    }
    sayHi();
<span class="kwrd">&lt;/</span><span class="html">script</span><span class="kwrd">&gt;</span></pre>
<p>这段代码很简单，我们定义了一个全局字符串对象name和函数对象sayHi。运行会弹出一个打招呼的对话框，“你好，我的名字叫Kevin Yang”。</p>
<p>我们把这段代码稍微改一改：</p>
<pre class="csharpcode"><span class="kwrd">&lt;</span><span class="html">script</span> <span class="attr">type</span><span class="kwrd">=&quot;text/javascript&quot;</span><span class="kwrd">&gt;</span>
    <span class="kwrd">var</span> name = <span class="str">&quot;Kevin Yang&quot;</span>;
    <span class="kwrd">function</span> sayHi(){
       alert(<span class="str">&quot;你好，我的名字叫&quot;</span> + <span class="kwrd">this</span>.name);
    }
    sayHi();
<span class="kwrd">&lt;/</span><span class="html">script</span><span class="kwrd">&gt;</span></pre>
<p>这段代码和上段代码的区别就在于sayHi函数在使用name的时候加上了this.前缀。运行结果和上面一摸一样。这说明this.name引用的也还是全局的name对象。</p>
<p>开头我们不是说了，函数也是普通的对象，可以将其当作一个普通变量使用。我们再把上面的代码改一改：</p>
<pre class="csharpcode"><span class="kwrd">&lt;</span><span class="html">script</span> <span class="attr">type</span><span class="kwrd">=&quot;text/javascript&quot;</span><span class="kwrd">&gt;</span>
    <span class="kwrd">var</span> name = <span class="str">&quot;Kevin Yang&quot;</span>;
    <span class="kwrd">function</span> sayHi(){
       alert(<span class="str">&quot;你好，我的名字叫&quot;</span> + <span class="kwrd">this</span>.name);
    }
    <span class="kwrd">var</span> person = {};
    person.sayHello = sayHi;
    person.sayHello();
<span class="kwrd">&lt;/</span><span class="html">script</span><span class="kwrd">&gt;</span></pre>
<p>这一次，我们又创建了一个全局对象person，并将sayHi函数对象赋给person对象的sayHello属性。运行结果如下：</p>
<p><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://www.imkevinyang.com/wp-content/uploads/2009/07/image-thumb.png" width="243" height="148" /> </p>
<p>这一次打招呼的内容就有点无厘头了，我们发现this.name已经变成undefined了。这说明，在sayHello函数内部执行时已经找不着this.name对象了。如果我们重新定义person对象，在其上面加上一个name属性又会怎么样呢？</p>
<pre class="csharpcode"><span class="kwrd">var</span> person = {name:<span class="str">&quot;Marry&quot;</span>};</pre>
<p>运行代码发现打招呼的“人”变了：</p>
<p><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://www.imkevinyang.com/wp-content/uploads/2009/07/image-thumb1.png" width="216" height="160" /> </p>
<p>是不是看出点道道了呢？</p>
<h2>判别this指针的指导性原则</h2>
<blockquote>
<p><strong>在Javascript里面，this指针代表的是执行当前代码的对象的<font color="#008000">所有者</font>。</strong></p>
</blockquote>
<p>在上面的示例中我们可以看到，第一次，我们定义了一个全局函数对象sayHi并执行了这个函数，函数内部使用了this关键字，那么执行this这行代码的对象是sayHi（一切皆对象的体现），sayHi是被定义在全局作用域中，因此sayHi的所有权是window对象的。其实在Javascript中所谓的全局对象，无非是定义在window这个根对象下的一个属性而已。也就是说，在全局作用域下，你可以通过直接使用name去引用这个对象，你也可以通过window.name去引用同一个对象。因而<strong><font color="#008000">this.name就可以翻译为window.name</font></strong>了。</p>
<p>再来看第二个this的示例。我们定义了一个person的对象，并定义了它的sayHello属性，使其指向sayHi全局对象。那么这个时候，当我们运行person.sayHello的时候，this所在的代码所属对象就是sayHello了（其实准确来说，sayHi和sayHello是只不过类似两个指针，指向的对象实际上是同一个），而sayHello对象的所有者就是person了。第一次，person里面没有name属性，因此弹出的对话框就是this.name引用的就是undefined对象（<font color="#008000"><strong>Javascript中所有只声明而没有定义的变量全都指向undefined对象</strong></font>）；而第二次我们在定义person的时候加了name属性了，那么this.name指向的自然就是我们定义的字符串了。</p>
<p>理解了上面所说的之后，我们将上面最后一段示例改造成面向对象式的代码。</p>
<pre class="csharpcode"><span class="kwrd">&lt;</span><span class="html">script</span> <span class="attr">type</span><span class="kwrd">=&quot;text/javascript&quot;</span><span class="kwrd">&gt;</span>
    <span class="kwrd">var</span> name = <span class="str">&quot;Kevin Yang&quot;</span>;
    <span class="kwrd">function</span> sayHi(){
       alert(<span class="str">&quot;你好，我的名字叫&quot;</span> + <span class="kwrd">this</span>.name);
    }
    <span class="kwrd">function</span> Person(name){
        <span class="kwrd">this</span>.name = name;
    }
    Person.prototype.sayHello = sayHi;
    <span class="kwrd">var</span> marry = <span class="kwrd">new</span> Person(<span class="str">&quot;Marry&quot;</span>);
    marry.sayHello();
    <span class="kwrd">var</span> kevin = <span class="kwrd">new</span> Person(<span class="str">&quot;Kevin&quot;</span>);
    kevin.sayHello();
<span class="kwrd">&lt;/</span><span class="html">script</span><span class="kwrd">&gt;</span></pre>
<p>在上面这段代码中，我们定义了一个Person的“类”（实际上还是一个对象），然后在这个类的原型（<strong><font color="#008000">类原型相当于C++中的静态成员变量的概念</font></strong>）中定义了sayHello属性，使其指向全局的sayHi对象。运行代码我们可以看到，marry和kevin都成功的向我们打了声“招呼”。</p>
<p>在这段代码中有两点需要思考的，一个是new我们很熟悉，但是在这里new到底做了什么操作呢？另外一个是，这里执行sayHello的时候，this指针为什么能够正确的指向marry和kevin对象呢？</p>
<p>我们来把上面定义“类”和实例化类对象的操作重新“翻译”一下：</p>
<pre class="csharpcode"><span class="kwrd">&lt;</span><span class="html">script</span> <span class="attr">type</span><span class="kwrd">=&quot;text/javascript&quot;</span><span class="kwrd">&gt;</span>
    <span class="kwrd">var</span> name = <span class="str">&quot;Kevin Yang&quot;</span>;
    <span class="kwrd">function</span> sayHi(){
       alert(<span class="str">&quot;你好，我的名字叫&quot;</span> + <span class="kwrd">this</span>.name);
    }
    <span class="kwrd">function</span> Person(name){
        <span class="kwrd">var</span> <span class="kwrd">this</span>;
        <span class="kwrd">this</span>.name = name;
        <span class="kwrd">return</span> <span class="kwrd">this</span>;
    }
    Person.prototype.sayHello = sayHi;
    <span class="kwrd">var</span> marry = Person(<span class="str">&quot;Marry&quot;</span>);
    marry.sayHello();
    <span class="kwrd">var</span> kevin = Person(<span class="str">&quot;Kevin&quot;</span>);
    kevin.sayHello();
<span class="kwrd">&lt;/</span><span class="html">script</span><span class="kwrd">&gt;</span></pre>
<p>当然这段代码并不能正确执行，但是它可以帮助你更好的理解这个过程。</p>
<p>当我们使用new关键字实例化一个“类”对象的时候，Javascript引擎会在这个对象内部定义一个新的对象并将其存入this指针。所有此对象内部用到this的代码实际上都是指向这个新的对象。如this.name = name，实际上是将参数中的name对象赋值给了这个新创建的对象。函数对象执行完之后Javascript引擎会将此对象返回给你，于是就有marry变量得到的对象的name为“Marry”，而kevin变量得到的对象的name属性确实“Kevin”。在这种情况下，this被强制赋给某个变量（类实例）了。</p>
<h2>显式操纵this指针</h2>
<p>在上面的面向对象式编程实例中，我们看到，在使用new操作符的情况下，看起来this的指向和我们前一节中讲到的指导原则并不相符。this指针并没有指向marry或者kevin的所有者，而是指向marry和kevin变量本身。</p>
<p>实际上，如果你理解什么是指针的话，那么你就会知道，既然是指针，那么当然可以改变其指向的对象。只不过Javascript引擎不允许我们自己写代码来做这样的事情，也就是说，在Javascript中，你不可以直接写this = someObj这样的代码。Javascript引擎通过以下两种方式允许我们显式指定this指针指代的对象：</p>
<p>1. 通过new操作符，Javascript引擎会将this指针返回给被赋值的变量A（对应上面的例子就是marry和kevin变量），这个时候A和this指针引用的就是同一个对象了，即A == this。过程参见上面的伪代码。</p>
<p>2. 通过Function.apply或者Function.call的原型方法，我们可以将this指针指代的对象以参数的形式传入，这个时候，函数内部使用的this指针就是传入的参数。</p>
<p>注意，对于这种显式指定this指针的情况，上一节提到的指导原则不再适用。</p>
<h2>容易误用的情况</h2>
<p>理解了this指针后，我们再来看看一些很容易误用this指针的情况。</p>
<p><strong>示例1——内联式绑定Dom元素的事件处理函数</strong></p>
<pre class="csharpcode"><span class="kwrd">&lt;</span><span class="html">script</span> <span class="attr">type</span><span class="kwrd">=&quot;text/javascript&quot;</span><span class="kwrd">&gt;</span>
    <span class="kwrd">function</span> sayHi(){
       alert(<span class="str">&quot;当前点击的元素是&quot;</span> + <span class="kwrd">this</span>.tagName);
    }
<span class="kwrd">&lt;/</span><span class="html">script</span><span class="kwrd">&gt;</span>
<span class="kwrd">&lt;</span><span class="html">input</span> <span class="attr">id</span><span class="kwrd">=&quot;btnTest&quot;</span> <span class="attr">type</span><span class="kwrd">=&quot;button&quot;</span> <span class="attr">value</span><span class="kwrd">=&quot;点击我&quot;</span> <span class="attr">onclick</span><span class="kwrd">=&quot;sayHi()&quot;</span><span class="kwrd">&gt;</span></pre>
<p>在此例代码中，我们绑定了button的点击事件，期望在弹出的对话框中打印出点击元素的标签名。但运行结果却是：</p>
<p><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://www.imkevinyang.com/wp-content/uploads/2009/07/image-thumb2.png" width="201" height="129" /> </p>
<p>也就是this指针并不是指向input元素。这是因为当使用内联式绑定Dom元素的事件处理函数时，实际上相当于执行了以下代码：</p>
<pre class="csharpcode"><span class="kwrd">&lt;</span><span class="html">script</span> <span class="attr">type</span><span class="kwrd">=&quot;text/javascript&quot;</span><span class="kwrd">&gt;</span>
    document.getElementById(<span class="str">&quot;btnTest&quot;</span>).onclick = <span class="kwrd">function</span>(){
        sayHi();
    }
<span class="kwrd">&lt;/</span><span class="html">script</span><span class="kwrd">&gt;</span></pre>
<p>在这种情况下<font color="#008000"><strong>sayHi函数对象的所有权并没有发生转移，还是属于window所有。</strong></font>用上面的指导原则一套我们就很好理解为什么this.tagName是undefined了。</p>
<p>那么如果我们要引用元素本身怎么办呢？</p>
<p>我们知道，onclick函数是属于btnTest元素的，那么在此函数内部，this指针正是指向此Dom对象，于是我们只需要把this作为参数传入sayHi即可。</p>
<pre class="csharpcode"><span class="kwrd">&lt;</span><span class="html">script</span> <span class="attr">type</span><span class="kwrd">=&quot;text/javascript&quot;</span><span class="kwrd">&gt;</span>
    <span class="kwrd">function</span> sayHi(el){
       alert(<span class="str">&quot;当前点击的元素是&quot;</span> + el.tagName);
    }
<span class="kwrd">&lt;/</span><span class="html">script</span><span class="kwrd">&gt;</span>
<span class="kwrd">&lt;</span><span class="html">input</span> <span class="attr">id</span><span class="kwrd">=&quot;btnTest&quot;</span> <span class="attr">type</span><span class="kwrd">=&quot;button&quot;</span> <span class="attr">value</span><span class="kwrd">=&quot;点击我&quot;</span> <span class="attr">onclick</span><span class="kwrd">=&quot;sayHi(this)&quot;</span><span class="kwrd">&gt;</span></pre>
<p>等价代码如下：</p>
<pre class="csharpcode"><span class="kwrd">&lt;</span><span class="html">script</span> <span class="attr">type</span><span class="kwrd">=&quot;text/javascript&quot;</span><span class="kwrd">&gt;</span>
    document.getElementById(<span class="str">&quot;btnTest&quot;</span>).onclick = <span class="kwrd">function</span>(){
        sayHi(<span class="kwrd">this</span>);
    }
<span class="kwrd">&lt;/</span><span class="html">script</span><span class="kwrd">&gt;</span></pre>
<p><strong>示例2——临时变量导致的this指针丢失</strong></p>
<pre class="csharpcode"><span class="kwrd">&lt;</span><span class="html">script</span> <span class="attr">type</span><span class="kwrd">=&quot;text/javascript&quot;</span><span class="kwrd">&gt;</span>
    <span class="kwrd">var</span> Utility = {
        decode:<span class="kwrd">function</span>(str){
            <span class="kwrd">return</span> unescape(str);
        },
        getCookie:<span class="kwrd">function</span>(key){
            <span class="rem">// ... 省略提取cookie字符串的代码</span>
            <span class="kwrd">var</span> value = <span class="str">&quot;i%27m%20a%20cookie&quot;</span>;
            <span class="kwrd">return</span> <span class="kwrd">this</span>.decode(value);
        }
    };
    alert(Utility.getCookie(<span class="str">&quot;identity&quot;</span>))
<span class="kwrd">&lt;/</span><span class="html">script</span><span class="kwrd">&gt;</span></pre>
<p>我们在写稍微有点规模的Js库的时候，一般都会自己封装一个Utility的类，然后将一些常用的函数作为Utility类的属性，如客户端经常会用到的getCookie函数和解码函数。如果每个函数都是彼此独立的，那么还好办，问题是，函数之间有时候会相互引用。例如上面的getCookie函数，会对从document.cookie中提取到的字符串进行decode之后再返回。如果我们通过Utility.getCookie去调用的话，那么没有问题，我们知道，getCookie内部的this指针指向的还是Utility对象，而Utility对象时包含decode属性的。代码可以成功执行。</p>
<p>但是有个人不小心这样使用Utility对象呢？</p>
<pre class="csharpcode"><span class="kwrd">&lt;</span><span class="html">script</span> <span class="attr">type</span><span class="kwrd">=&quot;text/javascript&quot;</span><span class="kwrd">&gt;</span>
    <span class="kwrd">function</span> showUserIdentity(){
        <span class="rem">// 保存getCookie函数到一个局部变量，因为下面会经常用到</span>
        <span class="kwrd">var</span> getCookie = Utility.getCookie;
        alert(getCookie(<span class="str">&quot;identity&quot;</span>));
    }
    showUserIdentity();
<span class="kwrd">&lt;/</span><span class="html">script</span><span class="kwrd">&gt;</span></pre>
<p>这个时候运行代码会抛出异常“this.decode is not a function”。运用上面我们讲到的指导原则，很好理解，因为此时Utility.getCookie对象被赋给了临时变量getCookie，而临时变量是属于window对象的——只不过外界不能直接引用，只对Javascript引擎可见——于是在getCookie函数内部的this指针指向的就是window对象了，而window对象没有定义一个decode的函数对象，因此就会抛出这样的异常来。</p>
<p>这个问题是由于引入了临时变量导致的this指针的转移。解决此问题的办法有几个：</p>
<ul>
<li>不引入临时变量，每次使用均使用Utility.getCookie进行调用 </li>
<li>getCookie函数内部使用Utility.decode显式引用decode对象而不通过this指针隐式引用（如果Utility是一个实例化的对象，也即是通过new生成的，那么此法不可用） </li>
<li>使用Funtion.apply或者Function.call函数指定this指针 </li>
</ul>
<p>前面两种都比较好理解，第三种需要提一下。正是因为this指针的指向很容易被转移丢失，因此Javascript提供了两个类似的函数apply和call来允许函数在调用时重新显式的指定this指针。</p>
<p>修正代码如下：</p>
<pre class="csharpcode"><span class="kwrd">&lt;</span><span class="html">script</span> <span class="attr">type</span><span class="kwrd">=&quot;text/javascript&quot;</span><span class="kwrd">&gt;</span>
    <span class="kwrd">function</span> showUserIdentity(){
        <span class="rem">// 保存getCookie函数到一个局部变量，因为下面会经常用到</span>
        <span class="kwrd">var</span> getCookie = Utility.getCookie;
        alert(getCookie.call(Utility,<span class="str">&quot;identity&quot;</span>));
        alert(getCookie.apply(Utility,[<span class="str">&quot;identity&quot;</span>]));
    }
    showUserIdentity();
<span class="kwrd">&lt;/</span><span class="html">script</span><span class="kwrd">&gt;</span></pre>
<p>call和apply只有语法上的差异，没有功能上的差别。</p>
<p><strong>示例3——函数传参时导致的this指针丢失</strong></p>
<p>我们先来看一段问题代码：</p>
<pre class="csharpcode"><span class="kwrd">&lt;</span><span class="html">script</span> <span class="attr">type</span><span class="kwrd">=&quot;text/javascript&quot;</span><span class="kwrd">&gt;</span>
    <span class="kwrd">var</span> person = {
        name:<span class="str">&quot;Kevin Yang&quot;</span>,
        sayHi:<span class="kwrd">function</span>(){
            alert(<span class="str">&quot;你好，我是&quot;</span>+<span class="kwrd">this</span>.name);
        }
    }
    setTimeout(person.sayHi,5000);
<span class="kwrd">&lt;/</span><span class="html">script</span><span class="kwrd">&gt;</span></pre>
<p>这段代码期望在访客进入页面5秒钟之后向访客打声招呼。setTimeout函数接收一个函数作为参数，并在指定的触发时刻执行这个函数。可是，当我们等了5秒钟之后，弹出的对话框显示的this.name却是undefined。</p>
<p>其实这个问题和上一个示例中的问题是类似的，都是因为临时变量而导致的问题。当我们执行函数的时候，如果函数带有参数，那么这个时候Javascript引擎会创建一个临时变量，并将传入的参数<strong><font color="#008000">复制（注意，Javascript里面都是值传递的，没有引用传递的概念）</font></strong>给此临时变量。也就是说，整个过程就跟上面我们定义了一个getCookie的临时变量，再将Utility.getCookie赋值给这个临时变量一样。只不过在这个示例中，容易忽视临时变量导致的bug。</p>
<h2>函数对象传参</h2>
<p>对于函数作为参数传递导致的this指针丢失的问题，目前很多框架都已经有方法解决了。</p>
<p><strong>Prototype的解决方案——传参之前使用bind方法将函数封装起来，并返回封装后的对象</strong></p>
<pre class="csharpcode"><span class="kwrd">&lt;</span><span class="html">script</span> <span class="attr">type</span><span class="kwrd">=&quot;text/javascript&quot;</span><span class="kwrd">&gt;</span>
    <span class="kwrd">var</span> person = {
        name:<span class="str">&quot;Kevin Yang&quot;</span>,
        sayHi:<span class="kwrd">function</span>(){
            alert(<span class="str">&quot;你好，我是&quot;</span>+<span class="kwrd">this</span>.name);
        }
    }
    <span class="kwrd">var</span> boundFunc = person.sayHi.bind(person);
    setTimeout(boundFunc,5000);
<span class="kwrd">&lt;/</span><span class="html">script</span><span class="kwrd">&gt;</span></pre>
<p>bind方法的实现其实是用到了Javascript又一个高级特性——闭包。我们来看一下源代码：</p>
<pre class="csharpcode"><span class="kwrd">function</span> bind(){
    <span class="kwrd">if</span> (arguments.length &lt; 2 &amp;&amp; arguments[0] === undefined)
        <span class="kwrd">return</span> <span class="kwrd">this</span>;
    <span class="kwrd">var</span> __method = <span class="kwrd">this</span>, args = $A(arguments), <span class="kwrd">object</span> = args.shift();
    <span class="kwrd">return</span> <span class="kwrd">function</span>(){
        <span class="kwrd">return</span> __method.apply(<span class="kwrd">object</span>, args.concat($A(arguments)));
    }
}</pre>
<style type="text/css">
<p>.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
<p>首先将this指针存入函数内部临时变量，然后在返回的函数对象中引用此临时变量从而形成闭包。</p>
<p><strong>微软的Ajax库提供的方案——构建委托对象</strong></p>
<pre class="csharpcode"><span class="kwrd">&lt;</span><span class="html">script</span> <span class="attr">type</span><span class="kwrd">=&quot;text/javascript&quot;</span><span class="kwrd">&gt;</span>
    <span class="kwrd">var</span> person = {
        name:<span class="str">&quot;Kevin Yang&quot;</span>,
        sayHi:<span class="kwrd">function</span>(){
            alert(<span class="str">&quot;你好，我是&quot;</span>+<span class="kwrd">this</span>.name);
        }
    }
    <span class="kwrd">var</span> boundFunc = Function.createDelegate(person,person.sayHi);
    setTimeout(boundFunc,5000);
<span class="kwrd">&lt;/</span><span class="html">script</span><span class="kwrd">&gt;</span></pre>
<p>其实本质上和prototype的方式是一样的。 </p>
<p>著名的Extjs库的解决方案采用的手法和微软是一样的。</p>
<p align="right">——<a href="http://www.imkevinyang.com/"><em><strong>Kevin Yang</strong></em></a></p>

	标签：<a href="http://www.imkevinyang.com/tags/javascript" title="Javascript" rel="tag">Javascript</a>, <a href="http://www.imkevinyang.com/tags/javascript%e9%ab%98%e7%ba%a7%e7%89%b9%e6%80%a7" title="Javascript高级特性" rel="tag">Javascript高级特性</a>, <a href="http://www.imkevinyang.com/tags/this%e6%8c%87%e9%92%88" title="this指针" rel="tag">this指针</a>, <a href="http://www.imkevinyang.com/categories/techarticles/web%e4%bc%a0%e7%bb%9f%e6%8a%80%e6%9c%af" title="Web传统技术" rel="tag">Web传统技术</a>, <a href="http://www.imkevinyang.com/tags/%e5%87%bd%e6%95%b0%e5%af%b9%e8%b1%a1%e4%bc%a0%e5%8f%82" title="函数对象传参" rel="tag">函数对象传参</a>, <a href="http://www.imkevinyang.com/categories/techarticles" title="技术随笔" rel="tag">技术随笔</a><br />

	<h4 style="background-color:#3B3B3B;border-bottom:2px groove gray;color:#F2F2F2;margin-top:20px;padding:6px 6px 6px 15px;margin:20px 0px 0px 0px">你可能对下面的文章感兴趣</h4>
	<ul class="st-related-posts">
	<li><a href="http://www.imkevinyang.com/2009/11/button%e6%a0%87%e7%ad%be%e9%bc%a0%e6%a0%87%e7%82%b9%e5%87%bb%e4%ba%8b%e4%bb%b6%e7%9a%84%e8%a7%a6%e5%8f%91%e6%ba%90%e9%97%ae%e9%a2%98.html" title="Button标签鼠标点击事件的触发源问题 (2009/11/27)">Button标签鼠标点击事件的触发源问题</a> </li>
	<li><a href="http://www.imkevinyang.com/2009/03/ie%e4%b8%ad%e4%bd%bf%e7%94%a8windowopen%e6%89%93%e5%bc%80%e6%96%b0%e7%aa%97%e5%8f%a3%e6%97%b6%e6%97%a0%e6%b3%95%e8%8e%b7%e5%8f%96referrer%e5%af%b9%e8%b1%a1.html" title="IE中使用window.open打开新窗口时无法获取Referrer对象 (2009/03/07)">IE中使用window.open打开新窗口时无法获取Referrer对象</a> </li>
	<li><a href="http://www.imkevinyang.com/2010/07/javajs%e5%a6%82%e4%bd%95%e4%bd%bf%e7%94%a8%e6%ad%a3%e5%88%99%e8%a1%a8%e8%be%be%e5%bc%8f%e5%8c%b9%e9%85%8d%e5%b5%8c%e5%a5%97html%e6%a0%87%e7%ad%be.html" title="Java/Js如何使用正则表达式匹配嵌套Html标签 (2010/07/30)">Java/Js如何使用正则表达式匹配嵌套Html标签</a> </li>
	<li><a href="http://www.imkevinyang.com/2009/07/javascript-%e4%b8%ad%e7%9a%84false%e9%9b%b6%e5%80%bcnullundefined%e5%92%8c%e7%a9%ba%e5%ad%97%e7%ac%a6%e4%b8%b2%e5%af%b9%e8%b1%a1.html" title="Javascript 中的false,零值,null,undefined和空字符串对象 (2009/07/07)">Javascript 中的false,零值,null,undefined和空字符串对象</a> </li>
	<li><a href="http://www.imkevinyang.com/2009/05/javascript%e4%b8%ad%e8%8e%b7%e5%8f%96%e5%87%ba%e9%94%99%e4%bb%a3%e7%a0%81%e6%89%80%e5%9c%a8%e6%96%87%e4%bb%b6%e5%8f%8a%e8%a1%8c%e6%95%b0.html" title="Javascript中获取出错代码所在文件及行数 (2009/05/18)">Javascript中获取出错代码所在文件及行数</a> </li>
	<li><a href="http://www.imkevinyang.com/2009/04/javascript%e5%ad%97%e7%ac%a6%e4%b8%b2%e5%93%88%e5%b8%8c%e5%87%bd%e6%95%b0.html" title="Javascript字符串哈希函数 (2009/04/11)">Javascript字符串哈希函数</a> </li>
	<li><a href="http://www.imkevinyang.com/2009/06/javascript%e6%93%8d%e7%ba%b5cookie.html" title="Javascript操纵Cookie (2009/06/11)">Javascript操纵Cookie</a> </li>
	<li><a href="http://www.imkevinyang.com/2010/05/%e4%b8%ba%e4%bb%80%e4%b9%88iis77-5%e7%9a%84gzip%e4%b8%8d%e8%b5%b7%e4%bd%9c%e7%94%a8.html" title="为什么IIS7/7.5的Gzip不起作用 (2010/05/08)">为什么IIS7/7.5的Gzip不起作用</a> </li>
	<li><a href="http://www.imkevinyang.com/2009/09/%e4%bd%bf%e7%94%a8%e7%9b%b8%e5%af%b9url%e6%97%a0%e7%bc%9d%e5%88%87%e6%8d%a2http-https.html" title="使用相对Url无缝切换HTTP-HTTPS (2009/09/18)">使用相对Url无缝切换HTTP-HTTPS</a> </li>
	<li><a href="http://www.imkevinyang.com/2010/07/%e5%87%a0%e4%b8%aa%e6%9c%89%e8%b6%a3%e7%9a%84javascript-hack.html" title="几个有趣的Javascript Hack (2010/07/23)">几个有趣的Javascript Hack</a> </li>
</ul>

]]></content:encoded>
			<wfw:commentRss>http://www.imkevinyang.com/2009/07/%e8%af%a6%e8%a7%a3javascript-%e4%b8%ad%e7%9a%84this%e6%8c%87%e9%92%88.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

<!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/

Page Caching using disk: enhanced

Served from: www.imkevinyang.com @ 2012-02-09 11:07:07 -->
