<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title type="text">博客园_笨蛋的座右铭</title><subtitle type="text">学习是一种信仰</subtitle><id>http://feed.cnblogs.com/blog/u/76597/rss</id><updated>2011-09-05T00:46:07Z</updated><author><name>笨蛋的座右铭</name><uri>http://www.cnblogs.com/fool/</uri></author><generator>feed.cnblogs.com</generator><link rel="alternate" type="text/html" href="http://www.cnblogs.com/fool/"/><link rel="self" type="application/atom+xml" href="http://feed.cnblogs.com/blog/u/76597/rss"/><entry><id>http://www.cnblogs.com/fool/archive/2010/10/20/1856303.html</id><title type="text">笨蛋的厄运</title><summary type="text">笨蛋也是有理想的。--笨蛋的座右铭</summary><published>2010-10-20T01:28:00Z</published><updated>2010-10-20T01:28:00Z</updated><author><name>笨蛋的座右铭</name><uri>http://www.cnblogs.com/fool/</uri></author><link rel="alternate" href="http://www.cnblogs.com/fool/archive/2010/10/20/1856303.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/fool/archive/2010/10/20/1856303.html"/><content type="html">&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2010/138960/2010102009183512.jpg" alt="" /&gt;&lt;/p&gt;&lt;p&gt;笨蛋也是有理想的。--笨蛋的座右铭&lt;/p&gt;&lt;img src="http://www.cnblogs.com/fool/aggbug/1856303.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/fool/archive/2010/10/20/1856303.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/fool/archive/2010/10/19/1855266.html</id><title type="text">理解Javascript_13_执行模型详解</title><summary type="text">在《理解Javascript_12_执行模型浅析》一文中,我们初步的了解了执行上下文与作用域的概念，那么这一篇将深入分析执行上下文的构建过程，了解执行上下文、函数对象、作用域三者之间的关系。函数执行环境简单的代码:当调用say方法时，第一步是创建其执行环境，在创建执行环境的过程中，会按照定义的先后顺序完成一系列操作:1.首先会创建一个'活动对象'(Activation Object)。活动对象是规...</summary><published>2010-10-18T21:13:00Z</published><updated>2010-10-18T21:13:00Z</updated><author><name>笨蛋的座右铭</name><uri>http://www.cnblogs.com/fool/</uri></author><link rel="alternate" href="http://www.cnblogs.com/fool/archive/2010/10/19/1855266.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/fool/archive/2010/10/19/1855266.html"/><content type="html">&lt;p&gt;在《&lt;a id="homepage1_HomePageDays_DaysList_ctl01_DayItem_DayList_ctl00_TitleUrl" class="postTitle1" href="http://www.cnblogs.com/fool/archive/2010/10/16/1853326.html"&gt;理解Javascript_12_执行模型浅析&lt;/a&gt;》一文中,我们初步的了解了执行上下文与作用域的概念，那么这一篇将深入分析执行上下文的构建过程，了解执行上下文、函数对象、作用域三者之间的关系。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 18pt;"&gt;&lt;strong&gt;函数执行环境&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;简单的代码:&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;function say(msg,other){&lt;br/&gt;var str = "nobody say:";&lt;br/&gt;this.name = '笨蛋的座右铭';&lt;br/&gt;function method(){};//var method = function(){};&lt;br/&gt;alert(str+msg);&lt;br/&gt;}&lt;br/&gt;say('hello world');&lt;br/&gt;alert(name);//笨蛋的座右铭&lt;br/&gt;&lt;/div&gt;&lt;p&gt;当调用say方法时，第一步是创建其执行环境，在创建执行环境的过程中，会按照定义的先后顺序完成一系列操作:&lt;/p&gt;&lt;p&gt;1.首先会创建一个'活动对象'(Activation Object)。活动对象是规范中规定的另外一种机制。之所以称之为对象，是因为它拥有可访问的命名属性，但是它又不像正常对象那样具有原型（至少没有预定义的原型），而且不能通过 JavaScript 代码直接引用活动对象。&lt;/p&gt;&lt;p&gt;2.为函数调用创建执行环境的下一步是创建一个 &lt;code&gt;arguments&lt;/code&gt; 对象，这是一个类似数组的对象，它以整数索引的数组成员一一对应地保存着调用函数时所传递的参数。这个对象也有 &lt;code&gt;length&lt;/code&gt; 和 &lt;code&gt;callee&lt;/code&gt; 属性（更深入的内容，请参见《&lt;a id="homepage1_HomePageDays_DaysList_ctl00_DayItem_DayList_ctl02_TitleUrl" class="postTitle1" href="http://www.cnblogs.com/fool/archive/2010/10/19/1855261.html"&gt;理解Javascript_14_函数形式参数与arguments&lt;/a&gt; 》）。然后，会为活动对象创建一个名为&amp;ldquo;arguments&amp;rdquo;的属性，该属性引用前面创建的 &lt;code&gt;arguments&lt;/code&gt;对象。&lt;/p&gt;&lt;p&gt;3.接着，为执行环境分配作用域。作用域由对象列表（链）组成。(比较复杂，请参见：《理解Javascript_15_作用域分配与变量访问规则,再送个闭包》)&lt;/p&gt;&lt;p&gt;4.之后会发生由 ECMA 262 中所谓'活动对象'完成的'变量实例化'(Variable Instatiation)的过程。此时会将函数的形式参数创建为可变对象的命名属性，如果调用函数时传递的参数与形式参数一致，则将相应参数的值赋给这些命名属性（否则，会给命名属性赋 &lt;code&gt;undefined&lt;/code&gt; 值）。对于定义的内部函数，会以其声明时所用名称为可变对象创建同名属性，而相应的内部函数则被创建为函数对象并指定给该属性。变量实例化的最后一步是将在函数内部声明的所有局部变量创建为可变对象的命名属性。&lt;strong&gt;注：在这个过程中，除了实际参数有值外和函数定义外，其它都被'预解析'为undefined值.&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;5.最后，要为使用 &lt;code&gt;this&lt;/code&gt; 关键字而赋值。(此时的this指向的是全局对象，即window)&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;执行环境创建成功后，就进入第二步：在函数体内,从上到下执行代码。&lt;/p&gt;&lt;p&gt;1.当执行到var str='nobody say'会发生称之为'计算赋值表达式'的过程，此时，会将活动对象中key为str的值从undefined设置为'nobody say:'。&lt;/p&gt;&lt;p&gt;2.执行到this.name='笨蛋的座右铭'时，会为作为this的对象添加属性name，并赋值为'笨蛋的座右铭'.&lt;/p&gt;&lt;p&gt;3.然后是执行function innerMethod(){};最后执行'alert(str+msg),输出'nobody say:hello world'.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 18pt;"&gt;&lt;strong&gt;function method(){}与var method = function(){}的区别&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;简单的代码：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;function say(){&lt;br/&gt;method01();//method01&lt;br/&gt;method02();//error&lt;br/&gt;function method01(){&lt;br/&gt;alert('method01');&lt;br/&gt;}&lt;br/&gt;var method02 = function(){&lt;br/&gt;alert('method02');&lt;br/&gt;}&lt;br/&gt;}&lt;br/&gt;&lt;br/&gt;say();&lt;/div&gt;&lt;p&gt;为什么调用方法method01能正常运行，而调用方法method02却会报错呢？&lt;/p&gt;&lt;p&gt;首先，你要明确的知道method01为一个函数对象，而method02为一个变量，它指向于另一个函数对象。根据上一节的内容，在'活动对象'完成的'变量实例化'(Variable Instatiation)的过程中，对函数method01进行了正常的'预解析'，而对于变量method02解析为undefined值，当进入到执行代码的环节时，因为method02的调用在其计算函数表达式之前，因此将undefined当作方法调来用，必然会报错。解决方案比较简单，就是将var method02=function(){...}放到其method02()的调用之前就可以了或者是用函数声明的方式定义函数(function method(){...})。&lt;/p&gt;&lt;p&gt;注：计算函数表达式就是指程序执行到var method02 = function(){...}。method02此时真正指向一个函数对象。因为在'预解析'时，method02只被赋于了undefined.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 18pt;"&gt;&lt;strong&gt;全局执行环境（《执行模型浅析》中已经讲过，不再深入)&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;在一个页面中，第一次载入JS代码时创建一个全局执行环境，全局执行环境的作用域链实际上只由一个对象,即全局对象(window),在开始JavaScript代码的执行之前，引擎会创建好这个Scope Chain结构。全局执行环境也会有变量实例化的过程，它的内部函数就是涉及大部分 JavaScript 代码的、常规的顶级函数声明。而且，在变量实例化过程中全局对象就是可变对象，这就是为什么全局性声明的函数是全局对象属性的原因。全局性声明的变量同样如此全局执行环境会使用 &lt;code&gt;this&lt;/code&gt; 对象来引用全局对象。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;注：区别'函数执行环境'中的活动对象(Activation Object)和全局执行环境中的可变对象(Vriable Object),Variable Object也叫做Activation Object(因为有一些差异存在，所以规范中重新取一个名字以示区别，全局执行环境/Eval执行环境中叫Variable Object，函数执行环境中就叫做Activation Object)。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 18pt;"&gt;&lt;strong&gt;Eval执行环境&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;构建Eval执行环境时的可变对象(Variable Object)就是调用eval时当前执行上下文中的可变对象(Variable Object)。在全局执行环境中调用eval函数，它的可变对象(Variable Object)就是全局对象；在函数中调用eval，它的可变对象(Variable Object)就是函数的活动对象(Activation Object)。&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;//Passed in FF2.0, IE7, Opera9.25, Safari3.0.4&lt;br/&gt;function fn(arg){&lt;br/&gt;    var innerVar = "variable in function";&lt;br/&gt;    eval(' \&lt;br/&gt;        var evalVar = "variable in eval"; \&lt;br/&gt;        document.write(arg + "&amp;lt;br /&amp;gt;"); \&lt;br/&gt;        document.write(innerVar + "&amp;lt;br /&amp;gt;"); \&lt;br/&gt;    ');&lt;br/&gt;    document.write(evalVar);&lt;br/&gt;}&lt;br/&gt;fn("arguments for function");&lt;/div&gt;&lt;p&gt;输出结果是:&lt;br /&gt;arguments for function&lt;br /&gt;variable in function&lt;br /&gt;variable in eval&lt;br /&gt;说明: eval调用中可以访问函数fn的参数、局部变量；在eval中定义的局部变量在函数fn中也可以访问，因为它们的Varible Object是同一个对象。&lt;/p&gt;&lt;p&gt;进入Eval Code执行时会创建一个新的Scope Chain，内容与当前执行上下文的Scope Chain完全一样。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 18pt;"&gt;&lt;strong&gt;最后的实例&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;代码如下：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;var outerVar1="variable in global code";&lt;br/&gt;function fn1(arg1, arg2){&lt;br/&gt;    var innerVar1="variable in function code";&lt;br/&gt;    function fn2() { return outerVar1+" - "+innerVar1+" - "+" - "+(arg1 + arg2); }&lt;br/&gt;    return fn2();&lt;br/&gt;}&lt;br/&gt;var outerVar2=fn1(10, 20);&lt;/div&gt;&lt;p&gt;执行处理过程大致如下:&lt;br /&gt;1. 初始化Global Object即window对象，Variable Object为window对象本身。创建Scope Chain对象，假设为scope_1，其中只包含window对象。&lt;br /&gt;2. 扫描JS源代码(读入源代码、可能有词法语法分析过程)，从结果中可以得到定义的变量名、函数对象。按照扫描顺序: &lt;br /&gt;&amp;nbsp;&amp;nbsp; 2.1 发现变量outerVar1，在window对象上添加outerVar1属性，值为undefined；&lt;br /&gt;&amp;nbsp;&amp;nbsp; 2.2 发现函数fn1的定义，使用这个定义创建函数对象，传给创建过程的Scope Chain为scope_1。将结果添加到window的属性中，名字为fn1，值为返回的函数对象。注意fn1的内部[[Scope]]就是 scope_1。另外注意，创建过程并不会对函数体中的JS代码做特殊处理，可以理解为只是将函数体JS代码的扫描结果保存在函数对象的内部属性上，在函数执行时再做进一步处理。这对理解Function Code，尤其是嵌套函数定义中的Variable Instantiation很关键；&lt;br /&gt;&amp;nbsp;&amp;nbsp; 2.3 发现变量outerVar2，在window对象上添加outerVar2属性，值为undefined；&lt;br /&gt;3. 执行outerVar1赋值语句，赋值为"variable in global code"。&lt;br /&gt;4. 执行函数fn1，得到返回值:&lt;br /&gt;&amp;nbsp;&amp;nbsp; 4.1 创建Activation Object，假设为activation_1；创建一个新的Scope Chain，假设为scope_2，scope_2中第一个对象为activation_1，第二个对象为window对象(取自fn1的 [[Scope]]，即scope_1中的内容)；&lt;br /&gt;&amp;nbsp;&amp;nbsp; 4.2 处理参数列表。在activation_1上设置属性arg1、arg2，值分别为10、20。创建arguments对象并进行设置，将arguments设置为activation_1的属性；&lt;br /&gt;&amp;nbsp;&amp;nbsp; 4.3 对fn1的函数体执行类似步骤2的处理过程:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 4.3.1 发现变量innerVar1，在activation_1对象上添加innerVar1属性，值为undefine；&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 4.3.2 发现函数fn2的定义，使用这个定义创建函数对象，传给创建过程的Scope Chain为scope_2(函数fn1的Scope Chain为当前执行上下文的内容)。将结果添加到activation_1的属性中，名字为fn2，值为返回的函数对象。注意fn2的内部 [[Scope]]就是scope_2；&lt;br /&gt;&amp;nbsp;&amp;nbsp; 4.4 执行innerVar1赋值语句，赋值为"variable in function code"。&lt;br /&gt;&amp;nbsp;&amp;nbsp; 4.5 执行fn2:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 4.5.1 创建Activation Object，假设为activation_2；创建一个新的Scope Chain，假设为scope_3，scope_3中第一个对象为activation_2，接下来的对象依次为activation_1、window 对象(取自fn2的[[Scope]]，即scope_2)；&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 4.5.2 处理参数列表。因为fn2没有参数，所以只用创建arguments对象并设置为activation_2的属性。&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 4.5.3 对fn2的函数体执行类似步骤2的处理过程，没有发现变量定义和函数声明。&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 4.5.4 执行函数体。对任何一个变量引用，从scope_3上进行搜索，这个示例中，outerVar1将在window上找到；innerVar1、arg1、arg2将在activation_1上找到。&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 4.5.5 丢弃scope_3、activation_2(指它们可以被垃圾回收了)。&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 4.5.6 返回fn2的返回值。&lt;br /&gt;&amp;nbsp;&amp;nbsp; 4.6 丢弃activation_1、scope_2。&lt;br /&gt;&amp;nbsp;&amp;nbsp; 4.7 返回结果。&lt;br /&gt;5. 将结果赋值给outerVar2。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;参考：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;http://www.cnblogs.com/RicCC/archive/2008/02/15/JavaScript-Object-Model-Execution-Model.html&lt;br/&gt;http://www.cn-cuckoo.com/2007/08/01/understand-javascript-closures-72.html&lt;br/&gt;&lt;/div&gt;&lt;img src="http://www.cnblogs.com/fool/aggbug/1855266.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/fool/archive/2010/10/19/1855266.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/fool/archive/2010/10/19/1855265.html</id><title type="text">理解Javascript_15_作用域分配与变量访问规则,再送个闭包</title><summary type="text">在阅读本博文之前，请先阅读《理解Javascript_13_执行模型详解》在'执行模型详解'中讲到了关于作用域分配的问题，这一篇博文将详细的说明函数对象、作用域链与执行上下文的关系。作用域分配与变量访问规则在 ECMAScript 中，函数也是对象。函数对象在变量实例化过程中会根据函数声明来创建，或者是在计算函数表达式或调用 Function 构造函数时创建。(关于'函数对象'请见《理解Jav...</summary><published>2010-10-18T20:42:00Z</published><updated>2010-10-18T20:42:00Z</updated><author><name>笨蛋的座右铭</name><uri>http://www.cnblogs.com/fool/</uri></author><link rel="alternate" href="http://www.cnblogs.com/fool/archive/2010/10/19/1855265.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/fool/archive/2010/10/19/1855265.html"/><content type="html">&lt;p&gt;在阅读本博文之前，请先阅读《理解Javascript_13_执行模型详解》&lt;/p&gt;&lt;p&gt;在'执行模型详解'中讲到了关于作用域分配的问题，这一篇博文将详细的说明函数对象、作用域链与执行上下文的关系。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 18pt;"&gt;&lt;strong&gt;作用域分配与变量访问规则&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;在 ECMAScript 中，函数也是对象。函数对象在变量实例化过程中会根据函数声明来创建，或者是在计算函数表达式或调用 &lt;code&gt;Function&lt;/code&gt; 构造函数时创建。(关于'函数对象'请见《&lt;a id="homepage1_HomePageDays_DaysList_ctl03_DayItem_DayList_ctl00_TitleUrl" class="postTitle1" href="http://www.cnblogs.com/fool/archive/2010/10/14/1851017.html"&gt;理解Javascript_08_函数对象&lt;/a&gt;》)。每个函数对象都有一个内部的 &lt;code&gt;[[scope]]&lt;/code&gt; 属性，这个属性也由对象列表（链）组成。这个内部的[[scope]]&amp;nbsp;属性引用的就是创建它们的执行环境的作用域链，同时，当前执行环境的活动对象被添加到该对象列表的顶部。当我们在函数内部访问变量时，其实就是在作用域链上寻找变量的过程。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;理论性太强了(总结死我了！)，还是让我们来看一段代码吧：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&amp;lt;script type="text/javascript"&amp;gt;&lt;br/&gt;function outer(){&lt;br/&gt;var i = 10;&lt;br/&gt;function inner(){&lt;br/&gt;var j = 100;&lt;br/&gt;alert(j);//100&lt;br/&gt;alert(i);//10&lt;br/&gt;alert(adf);&lt;br/&gt;}&lt;br/&gt;inner();&lt;br/&gt;}&lt;br/&gt;outer();&lt;br/&gt;&amp;lt;/script&amp;gt;&lt;/div&gt;&lt;p&gt;下图清晰的展现了上述代码的内存分配与作用域分配情况:&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2010/138960/2010101903461985.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;下面来解释一下：&lt;/p&gt;&lt;p&gt;1.载入代码，创建全局执行环境，此时会在可变对象(window)中添加outer变量，其指向于函数对象outer,此时作用域链中只有window对象.&lt;/p&gt;&lt;p&gt;2.执行代码，当程序执行到outer()时，会在全局对象中寻找outer变量，成功调用。&lt;/p&gt;&lt;p&gt;3.创建outer的执行环境，此时会新创建一个活动对象，添加变量i，设置值为10,添加变量inner，指向于函数对象inner.并将活动对象压入作用域链中.并将函数对象outer的[[scope]]属性指向活动对象outer。此时作用域链为outer的活动对象+window.&lt;/p&gt;&lt;p&gt;4.执行代码，为 i 成功赋值。当程序执行到inner()时，会在函数对象outer的[[scope]]中寻找inner变量。找到后成功调用。&lt;/p&gt;&lt;p&gt;5.创建inner的执行环境，新建一个活动对象，添加变量j，赋值为100,并将该活动对象压入作用域链中，并函数对象inner的[[scope]]属性指向活动对象inner.此时作用域链为:inner的活动对象+outer的活动对象+全局对象.&lt;/p&gt;&lt;p&gt;6.执行代码为j赋值，当访问i、j时成功在作用域中找到对应的值并输出，而当访问变量adf时，没有在作用域中寻找到，访问出错。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;注：通过内存图，我们会发现作用域链与prototype链是如此的相象。这说明了很多问题...(仁者见仁智者见智,自己探寻答案吧！)&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 18pt;"&gt;&lt;strong&gt;闭包原理&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;在我们了解了作用域的问题之后，对于闭包这个问题已经很简单了。什么是闭包？闭包就是封闭了外部函数作用域中变量的内部函数。&lt;/p&gt;&lt;p&gt;我们来看一个典型的闭包运用：生成increment值&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&amp;lt;script type="text/javascript"&amp;gt;&lt;br/&gt;var increment = (function(){&lt;br/&gt;var id = 0;&lt;br/&gt;return function(){&lt;br/&gt;return ++id;&lt;br/&gt;}&lt;br/&gt;})()&lt;br/&gt;&lt;br/&gt;alert(increment());//1&lt;br/&gt;alert(increment());//2&lt;br/&gt;&amp;lt;/script&amp;gt;&lt;/div&gt;&lt;p&gt;外层匿名函数返回的是一个内嵌函数，内嵌函数使用了外层匿名函数的局部变量id。照理外层匿名函数的局部变量在返回时就超出了作用域因此increment()调用无法使用才对。这就是闭包Closure，即函数调用返回了一个内嵌函数，而内嵌函数引用了外部函数的局部变量、参数等这些应当被关闭(Close)了的资源。这是怎么一回事呢？让我们来寻找答案：&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2010/138960/2010101904411936.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;根据Scope Chain的理解可以解释，返回的内嵌函数已经持有了构造它时的Scope Chain，虽然outer返回导致这些对象超出了作用域、生存期范围，但JavaScript使用自动垃圾回收来释放对象内存: 按照规则定期检查，对象没有任何引用才被释放。因此上面的代码能够正确运行。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;参考：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;a href="http://www.cnblogs.com/RicCC/archive/2008/02/15/JavaScript-Object-Model-Execution-Model.htmlhttp://www.cn-cuckoo.com/2007/08/01/understand-javascript-closures-72.html"&gt;http://www.cnblogs.com/RicCC/archive/2008/02/15/JavaScript-Object-Model-Execution-Model.html&lt;br/&gt;http://www.cn-cuckoo.com/2007/08/01/understand-javascript-closures-72.html&lt;br/&gt;&lt;/a&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/fool/aggbug/1855265.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/fool/archive/2010/10/19/1855265.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/fool/archive/2010/10/19/1855261.html</id><title type="text">理解Javascript_14_函数形式参数与arguments</title><summary type="text">在'执行模型详解'的'函数执行环境'一节中对arguments有了些许的了解，那么让我们深入的分析一下函数的形式参数与arguments的关系。注：在阅读本博文前请先阅读《理解javascript_13_执行模型详解》注：本文的部分内容是自已的一些推论，并无官文文档作依据，如有错误之后，还望指正。生涩的代码我们先来看一段比较生涩的代码：你能正确的解释代码的执行结果吗？思考一下.我想代码运行...</summary><published>2010-10-18T17:49:00Z</published><updated>2010-10-18T17:49:00Z</updated><author><name>笨蛋的座右铭</name><uri>http://www.cnblogs.com/fool/</uri></author><link rel="alternate" href="http://www.cnblogs.com/fool/archive/2010/10/19/1855261.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/fool/archive/2010/10/19/1855261.html"/><content type="html">&lt;p&gt;在'执行模型详解'的'函数执行环境'一节中对arguments有了些许的了解，那么让我们深入的分析一下函数的形式参数与arguments的关系。&lt;/p&gt;&lt;p&gt;注：在阅读本博文前请先阅读《理解javascript_13_执行模型详解》&lt;/p&gt;&lt;p&gt;注：本文的部分内容是自已的一些推论，并无官文文档作依据，如有错误之后，还望指正。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 18pt;"&gt;&lt;strong&gt;生涩的代码&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;我们先来看一段比较生涩的代码：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;function say(msg,other,garbage){&lt;br/&gt;alert(arguments[1]);//world&lt;br/&gt;var other = 'nice to meet you!';&lt;br/&gt;var msg;&lt;br/&gt;alert(arguments.length);&lt;br/&gt;alert(msg);//hello&lt;br/&gt;alert(other);//nice to meet you!&lt;br/&gt;alert(arguments[1]);//nice to meet you!&lt;br/&gt;alert(garbage);//undefined&lt;br/&gt;}&lt;br/&gt;say('hello','world');&lt;/div&gt;&lt;p class="p0"&gt;你能正确的解释代码的执行结果吗？思考一下.&lt;/p&gt;&lt;p class="p0"&gt;我想代码运行的结果，应该会和你的想象有很大的出入吧！为什么msg正常输出为hello，而不是undefined呢？函数定义的参数和函数内部定义的变量重复了会发生什么呢？arguments和函数定义时的参数有什么关系呢？让我们来一一解答：&lt;/p&gt;&lt;p class="p0"&gt;&amp;nbsp;&lt;/p&gt;&lt;p class="p0"&gt;&lt;span style="font-size: 18pt;"&gt;&lt;strong&gt;简单的内存图&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2010/138960/2010101901333790.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 8pt;"&gt;注：虚线表示的是曾经引用的指向。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 18pt;"&gt;&lt;strong&gt;解答&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;首先，我们来了解两个概念,形式参数和实际参数。形式参数指的是定义方法时所明确指定的参数，由于Javascript语言的灵活性，javascript并不要求方法调用时，所传递的参数个数与形式参数一致.而javascript实际调用时所传递的参数就是实际参数。arguments指的就是实际参数。从say方法中可以看出，say定义了三个形式参数，而实际调用时只传递了两个值。因此arguments.length的值为2,而不是3.接着我们来看一下arguments的特殊行为，个人感觉arguments会将所有的实际参数都当作对象来看待，对于基本数据类型的实际参数则会转换为其对应的对象类型。这是根据在函数内定义与形式参数同名的变量并赋值，arguments对应的值会跟着改变来判断的。&lt;/p&gt;&lt;p&gt;接着我们来分析一下构建say方法执行上下文的过程，由于逻辑比较复杂，这里我写一些'伪代码'来进行说明：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;function say(msg,other,garbage){&lt;br/&gt;//先对函数声明的变量进行'预解析',内部执行流程，它是是不可见的&lt;br/&gt;var msg = undefined;&lt;br/&gt;var other = undefined;&lt;br/&gt;var garbage = undefined;&lt;br/&gt;//再对函数内部定义的变量进行'预解析'&lt;br/&gt;var other = undefined;//很明显，此时这个定义已经无意义了。&lt;br/&gt;var msg = undefined;//无意义&lt;br/&gt;&lt;br/&gt;//对实际参数进行赋值操作&lt;br/&gt;msg = new String('hello');//arguments的会将所有实际参数当作对象看待&lt;br/&gt;other = new String('world');&lt;br/&gt;&lt;br/&gt;//正式进入函数代码部分&lt;br/&gt;alert(arguments[1]);//world&lt;br/&gt;other = 'nice to meet you!';&lt;br/&gt;//var msg;这个已经被预解析了，因此不会再执行&lt;br/&gt;alert(arguments.length);//2&lt;br/&gt;alert(msg);//hello&lt;br/&gt;alert(other);//nice to meet you!&lt;br/&gt;alert(arguments[1]);//nice to meet you!&lt;br/&gt;alert(garbage);//undefined&lt;br/&gt;}&lt;/div&gt;&lt;p&gt;这段代码已经可以解释一面的所有的问题了。我就不多说了。&lt;/p&gt;&lt;p&gt;唯一强调的一点是在内部用var定义与形式参数同名的变量是无意义的，因为在程序'预解析'后，会将它们看作为同一个变量。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 18pt;"&gt;&lt;strong&gt;其它&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;关于arguments还有很多特性，我在《&lt;a id="homepage1_HomePageDays_ctl00_DayList_ctl02_TitleUrl" class="postTitle1" href="http://www.cnblogs.com/fool/archive/2010/10/09/1846966.html"&gt;伪数组&lt;/a&gt;》一文中提到也提到了arguments,有兴趣的读者可以去看一下。arguments的实际应用你还可以参考一下这一篇文章 ：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;a href="http://www.gracecode.com/archives/2551/"&gt;http://www.gracecode.com/archives/2551/&lt;/a&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;好了，也就这么多了。希望大家能多多指正，多提意见吧。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/fool/aggbug/1855261.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/fool/archive/2010/10/19/1855261.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/fool/archive/2010/10/17/1853813.html</id><title type="text">超越Jquery_01_isPlainObject分析与重构</title><summary type="text">isPlainObject是Jquery1.4后提供的新方法,用于判断对象是否是纯粹的对象（通过 "{}" 或者 "new Object" 创建的）。使用isPlainObject首先我们来了解一下什么叫'纯粹的对象'，简单的理解'纯粹的对象'指的就是由Object构造出来的对象。那哪些对象是由Object构造出来的呢。首当其充的肯定是由new Object()所构造出来的对象，注意：在Obj...</summary><published>2010-10-17T13:10:00Z</published><updated>2010-10-17T13:10:00Z</updated><author><name>笨蛋的座右铭</name><uri>http://www.cnblogs.com/fool/</uri></author><link rel="alternate" href="http://www.cnblogs.com/fool/archive/2010/10/17/1853813.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/fool/archive/2010/10/17/1853813.html"/><content type="html">&lt;p&gt;isPlainObject是Jquery1.4后提供的新方法,用于判断对象是否是纯粹的对象（通过 "{}" 或者 "new Object" 创建的）。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 18pt;"&gt;&lt;strong&gt;使用isPlainObject&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;首先我们来了解一下什么叫'纯粹的对象'，简单的理解'纯粹的对象'指的就是由Object构造出来的对象。那哪些对象是由Object构造出来的呢。首当其充的肯定是由new Object()所构造出来的对象，注意：在Object后的括号里可没加任何东西。因为Object是所有'类'的根基，因此它有一些特殊的行为,如当调用new Object(3)的时候，会构造一个Number类型的对象。new Object('')会构造一个String类型的对象。然后以{}这种形式定义的对象也属于'纯粹的对象'。'{}'的实质就是new Object()，只是表现形形式不同。好，让我们来看一段代码：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;var objStr = new Object('');&lt;br/&gt;alert(objStr.constructor);//String&lt;br/&gt;alert(isPlainObject(objStr));//false&lt;br/&gt;var objNum = new Object(3);&lt;br/&gt;alert(objNum.constructor);//Number&lt;br/&gt;alert(isPlainObject(objNum));//false&lt;br/&gt;&lt;br/&gt;function Person(){}&lt;br/&gt;var person = new Person();&lt;br/&gt;alert(isPlainObject(person));//false&lt;br/&gt;&lt;br/&gt;var obj01 = new Object();&lt;br/&gt;obj01.name = '笨蛋的座右铭';&lt;br/&gt;alert(isPlainObject(obj01));//true&lt;br/&gt;alert(isPlainObject({name:'笨蛋的座右铭'}));//true&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 18pt;"&gt;&lt;strong&gt;isPlainObject源码分析&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;以下代码为Jquery中的isPlainObject的完整版本,注释已经很详尽了，我就不多说什么了。&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;var toString = Object.prototype.toString,&lt;br/&gt;hasOwnProperty = Object.prototype.hasOwnProperty;&lt;br/&gt;&lt;br/&gt;function isPlainObject( obj ) {&lt;br/&gt;// Must be an Object.&lt;br/&gt;// Because of IE, we also have to check the presence of the constructor property.&lt;br/&gt;&lt;br/&gt;//Make sure that DOM nodes and window objects don't pass through, as well&lt;br/&gt;//windows objects:toString.call(window):IE [object Object] FF [object Window] chrome [window global] safari [object DOMWindow]&lt;br/&gt;//DOM nodes:toString.call(#div01):IE [object Object] FF [object Window] chrome [object global] safari [object DOMWindow]&lt;br/&gt;//结论：obj.nodeType || obj.setInterval主要是针对于IE浏览器进行判断&lt;br/&gt;//注：history,location,navigator,screen的setInterval为undefined&lt;br/&gt;if ( !obj || toString.call(obj) !== "[object Object]" || obj.nodeType || obj.setInterval ) {&lt;br/&gt;return false;&lt;br/&gt;}&lt;br/&gt;&lt;br/&gt;// Not own constructor property must be Object&lt;br/&gt;// 除去自定义对象和内置对象的判断,如function Person(){} var p = new Person();String,Number&lt;br/&gt;if ( obj.constructor //有constructor属性&lt;br/&gt;&amp;amp;&amp;amp; !hasOwnProperty.call(obj, "constructor") //并且constructor这个属性必须是在原型链中进行定义的&lt;br/&gt;&amp;amp;&amp;amp; !hasOwnProperty.call(obj.constructor.prototype, "isPrototypeOf")//并且原型中有isPrototypeOf方法，一般只有Object的原型中才有这个方法&lt;br/&gt;) {&lt;br/&gt;return false;&lt;br/&gt;}&lt;br/&gt;&lt;br/&gt;// Own properties are enumerated firstly, so to speed up,&lt;br/&gt;// if last one is own, then all properties are own.&lt;br/&gt;//针对于复杂类结构，如有继承...&lt;br/&gt;/*&lt;br/&gt;//一个简单的测试&lt;br/&gt;function Animal(name){&lt;br/&gt;&lt;br/&gt;}&lt;br/&gt;function Person(name,age){&lt;br/&gt;Animal.call(this,name);&lt;br/&gt;this.age =age;&lt;br/&gt;}&lt;br/&gt;var p = new Person('jxl',20);&lt;br/&gt;for(key in p){&lt;br/&gt;alert(hasOwnProperty.call( p, key ))//true,false&lt;br/&gt;}&lt;br/&gt;*/&lt;br/&gt;var key;&lt;br/&gt;for ( key in obj ) {}&lt;br/&gt;&lt;br/&gt;return key === undefined || hasOwnProperty.call( obj, key );&lt;br/&gt;}&lt;/div&gt;&lt;p&gt;&lt;span style="font-size: 18pt;"&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/span&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 18pt;"&gt;&lt;strong&gt;提出问题&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;个人感觉这个实现比较复杂，而且有BUG。&lt;/p&gt;&lt;p&gt;简单的BUG,history,location,navigator,screen可以顺序通过&amp;nbsp;isPlainObject的检测返回true.&lt;/p&gt;&lt;p&gt;来看一个我的解决方案(修改BUG，简化):&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;function isPlainObject(obj){&lt;br/&gt;if(obj&amp;amp;&amp;amp;Object.prototype.toString.call(obj)==="[object Object]"&amp;amp;&amp;amp;obj.constructor===Object &amp;amp;&amp;amp;!hasOwnProperty.call(obj, "constructor")){&lt;br/&gt;var key;&lt;br/&gt;for ( key in obj ) {}&lt;br/&gt;return key === undefined || hasOwnProperty.call( obj, key );&lt;br/&gt;}&lt;br/&gt;return false;&lt;br/&gt;}&lt;/div&gt;&lt;p&gt;还有BUG，而且是一个无解的BUG：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;function m(){}; &lt;br/&gt;m.prototype.constructor=Object;  //必杀&lt;br/&gt;obj=new m;  &lt;br/&gt;alert(isPlainObject(obj));  //true&lt;/div&gt;&lt;p&gt;再来一个同理的:&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;function m(){}; &lt;br/&gt;m.prototype = {};&lt;br/&gt;obj=new m;  &lt;br/&gt;alert(isPlainObject(obj)); //true&lt;/div&gt;&lt;p&gt;这个答案是无解的！&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 18pt;"&gt;&lt;strong&gt;解答无解&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;本以为这个问题很好解决，结果深入后，发现这是一个无解的问题。原因如下：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;function Person(){}; &lt;br/&gt;Person.prototype.constructor=Object;  &lt;br/&gt;var person=new Person;  &lt;/div&gt;&lt;p&gt;让我们来看一下person现在的状态：&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2010/138960/2010101721090783.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;person和其构造函数Person唯一的联系就是其prototype链中的constructor属性。而在我们判断是否为'纯粹的对象'主要是依据对象实例的constructor进行的。如果我们将其指向Object，正如图中看到的那样，那么person和Person在代码上就没有关系了。也正是因为这一点，让类型的判断出现了问题。&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/fool/aggbug/1853813.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/fool/archive/2010/10/17/1853813.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/fool/archive/2010/10/16/1853326.html</id><title type="text">理解Javascript_12_执行模型浅析</title><summary type="text">大家有没有想过，一段javascript脚本从载入浏览器到显示执行都经过了哪些流程，其执行次序又是如何。本篇博文将引出'javascript执行模型'的概念，并带领大家理解javascript在执行时的处理机制。简单的开始简单的代码：上面代码段的运行顺序是：对于step1中的'脚本段'指的是&lt;script&gt;... ...&lt;/script&gt;标签中的内容，还包括外部引入的脚本文...</summary><published>2010-10-16T15:56:00Z</published><updated>2010-10-16T15:56:00Z</updated><author><name>笨蛋的座右铭</name><uri>http://www.cnblogs.com/fool/</uri></author><link rel="alternate" href="http://www.cnblogs.com/fool/archive/2010/10/16/1853326.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/fool/archive/2010/10/16/1853326.html"/><content type="html">&lt;p&gt;大家有没有想过，一段javascript脚本从载入浏览器到显示执行都经过了哪些流程，其执行次序又是如何。本篇博文将引出'javascript执行模型'的概念，并带领大家理解javascript在执行时的处理机制。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 18pt;"&gt;&lt;strong&gt;简单的开始&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;简单的代码：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&amp;lt;script type="text/javascript" src="xxx.js"&amp;gt;&amp;lt;/script&amp;gt;&lt;br/&gt;&amp;lt;script type="text/javascript"&amp;gt;&lt;br/&gt;var i = 10;&lt;br/&gt;function say(msg){&lt;br/&gt;alert(msg);&lt;br/&gt;}&lt;br/&gt;&amp;lt;/script&amp;gt;&lt;br/&gt;&amp;lt;script type="text/javascript"&amp;gt;&lt;br/&gt;j=100;&lt;br/&gt;say("hello world");&lt;br/&gt;&amp;lt;/script&amp;gt;&lt;/div&gt;&lt;p&gt;上面代码段的运行顺序是：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;step1. 读入第一个代码段&lt;br/&gt;step2. 做语法分析，有错则报语法错误（比如括号不匹配等），并跳转到step5&lt;br/&gt;step3. 创建全局执行环境(对var变量和function定义做"预解析")&lt;br/&gt;step4. 执行代码段(调用函数、进入eval时，都会创建新的执行环境)，有错则报错（比如变量未定义）&lt;br/&gt;step5. 如果还有下一个代码段，则读入下一个代码段，重复step2&lt;br/&gt;step6. 结束&lt;/div&gt;&lt;p&gt;对于step1中的'脚本段'指的是&amp;lt;script&amp;gt;... ...&amp;lt;/script&amp;gt;标签中的内容，还包括外部引入的脚本文件，如&amp;lt;script src="xxx.js"&amp;gt;&amp;lt;/script&amp;gt;也被列是脚本段的范畴。那step2中的语法分析又是什么呢？简单的理解语法分析就是查看Javascript代码的语法结构是否正确。如:&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&amp;lt;script type="text/javascript"&amp;gt;&lt;br/&gt;var a = 10;&lt;br/&gt;if(a&amp;gt;10{&lt;br/&gt;alert('yes');&lt;br/&gt;}&lt;br/&gt;&amp;lt;/script&amp;gt;&lt;/div&gt;&lt;p&gt;很明显，代码无法通过语法分析，if这个条件语句的输写语法是错误的。step3和step4中的'执行环境'是指什么，全局执行环境和调用函数创建的执行环境有什么区别?执行环境内部又有哪些处理?... ...&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;注：下面的部分内容为原来《javascript提速_01_引用变量优化》一文中的前两节的完整版本。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 18pt;"&gt;&lt;strong&gt;关于执行环境(Execution Context)&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;所有 JavaScript 代码都是在一个执行环境中被执行的。它是一个概念，一种机制，用来完成JavaScript运行时作用域、生存期等方面的处理。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;可执行的JavaScript代码分三种类型：&lt;br /&gt;1. Global Code，即全局的、不在任何函数里面的代码，例如：一个js文件、嵌入在HTML页面中的js代码等。&lt;br /&gt;2. Eval Code，即使用eval()函数动态执行的JS代码。&lt;br /&gt;3. Function Code，即用户自定义函数中的函数体JS代码。&lt;/p&gt;&lt;p&gt;不同类型的JavaScript代码具有不同的Execution Context&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;在一个页面中，第一次载入JS代码时创建一个全局执行环境，当调用一个 JavaScript 函数时，该函数就会进入相应的执行环境。如果又调用了另外一个函数（或者递归地调用同一个函数），则又会创建一个新的执行环境，并且在函数调用期间执行过程都处于该环境中。当调用的函数返回后，执行过程会返回原始执行环境。因而，运行中的 JavaScript 代码就构成了一个执行环境栈。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;让我们来看一个示例：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&amp;lt;script type="text/javascript"&amp;gt;&lt;br/&gt;function Fn1(){&lt;br/&gt;function Fn2(){&lt;br/&gt;alert(document.body.tagName);//BODY&lt;br/&gt;//other code...&lt;br/&gt;}&lt;br/&gt;Fn2();&lt;br/&gt;}&lt;br/&gt;Fn1();&lt;br/&gt;//code here&lt;br/&gt;&amp;lt;/script&amp;gt;&lt;/div&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2010/138960/2010101622105252.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;以上是程序从上到下执行时的执行环境栈情况图。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;补充说明：&lt;/p&gt;&lt;p&gt;全局执行环境对应的是Global Code(全局代码)&lt;/p&gt;&lt;p&gt;Fn1执行环境、Fn2执行环境通称为函数执行环境对应的是Function Code(函数定义代码)&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;程序在进入每个执行环境的时候都会创建一个叫做Variable Object的对象。&lt;/p&gt;&lt;p&gt;针对于函数执行环境，函数对应的每一个参数、局部变量、内部方法都会在Variable Object上创建一个属性，属性名为变量名，属性值为变量值。针对于全局执行环境，具有相同的行为。但是要强调的一点是在全局执行环境中Varible Object就是Global Object,关于Global Object在《&lt;span style="color: #333333;"&gt;&lt;a id="PostsList1_rpPosts_ctl00_TitleUrl" href="http://www.cnblogs.com/fool/archive/2010/10/08/1846078.html"&gt;理解Javascript_03_javascript全局观&lt;/a&gt;》中已经说明了，可以简单的理解为window对象。这也就解释了全局方法和全局变量为什么都是window对象的属性或方法的原因，请看如下代码：&lt;/span&gt;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;var num = 123;&lt;br/&gt;alert(window.num);//123&lt;br/&gt;function say(msg){&lt;br/&gt;alert(msg);&lt;br/&gt;}&lt;br/&gt;window.say("hello");//hello&lt;/div&gt;&lt;p&gt;最后要说的是，Variable Object对象是一个内部对象，JS代码中无法直接访问。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 18pt;"&gt;&lt;strong&gt;关于Scope/Scope Chain&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;在访问变量时，就必须存在一个可见性的问题，这就是Scope。更深入的说，当访问一个变量或调用一个函数时，JavaScript引擎将不同执行位置上的Variable Object按照规则构建一个链表，在访问一个变量时，先在链表的第一个Variable Object上查找，如果没有找到则继续在第二个Variable Object上查找，直到搜索结束。这也就形成了Scope Chain的概念。&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2010/138960/2010101700034040.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;作用域链图，清楚的表达了执行环境与作用域的关系(一一对应的关系)，作用域与作用域之间的关系(链表结构，由上至下的关系)。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;注：本文仅仅从全局角度的看待javascript执行模型，因此不够深入，具体执行细节，请参见后续博文。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;参考：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;http://www.cnblogs.com/RicCC/archive/2008/02/15/JavaScript-Object-Model-Execution-Model.html&lt;br/&gt;http://www.cn-cuckoo.com/2007/08/01/understand-javascript-closures-72.html&lt;br/&gt;http://lifesinger.org/blog/2009/01/javascript-run-mechanism/&lt;br/&gt;&lt;/div&gt;&lt;img src="http://www.cnblogs.com/fool/aggbug/1853326.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/fool/archive/2010/10/16/1853326.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/fool/archive/2010/10/16/1853126.html</id><title type="text">理解Javascript_11_constructor实现原理</title><summary type="text">在理解了'对象模型'后,我们就可以看一下constructor属性是如何实现的.constructor是什么简单的理解,constructor指的就是对象的构造函数。请看如下示例：对于foo.constructor为Foo,我想应该很好理解，因为foo的构造函数为Foo。对于Foo、Object、Function的构造函数为Function,我想也没什么好争议的。（因为Foo,Object,Fun...</summary><published>2010-10-16T08:27:00Z</published><updated>2010-10-16T08:27:00Z</updated><author><name>笨蛋的座右铭</name><uri>http://www.cnblogs.com/fool/</uri></author><link rel="alternate" href="http://www.cnblogs.com/fool/archive/2010/10/16/1853126.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/fool/archive/2010/10/16/1853126.html"/><content type="html">&lt;p&gt;在理解了'对象模型'后,我们就可以看一下constructor属性是如何实现的.&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 18pt;"&gt;&lt;strong&gt;constructor是什么&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;简单的理解,constructor指的就是对象的构造函数。请看如下示例：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;function Foo(){};&lt;br/&gt;var foo = new Foo();&lt;br/&gt;alert(foo.constructor);//Foo&lt;br/&gt;alert(Foo.constructor);//Function&lt;br/&gt;alert(Object.constructor);//Function&lt;br/&gt;alert(Function.constructor);//Function&lt;/div&gt;&lt;p&gt;对于foo.constructor为Foo,我想应该很好理解，因为foo的构造函数为Foo。对于Foo、Object、Function的构造函数为Function,我想也没什么好争议的。（因为Foo,Object,Function都是函数对象，又因为所有的函数对象都是Function这个函数对象构造出来,所以它们的constructor为Function,详细请参考《js_函数对象》)&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 18pt;"&gt;&lt;strong&gt;Prototype与Constructor的关系&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;function Dog(){}&lt;br/&gt;alert(Dog === Dog.prototype.constructor);//true&lt;/div&gt;&lt;p&gt;在 JavaScript 中，每个函数都有名为&amp;ldquo;prototype&amp;rdquo;的属性，用于引用原型对象。此原型对象又有名为&amp;ldquo;constructor&amp;rdquo;的属性，它反过来引用函数本身。这是一种循环引用，如图：&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2010/138960/2010101615092176.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 18pt;"&gt;&lt;strong&gt;constructor属性来自何方&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;我们来看一下Function构造String的构造过程：&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2010/138960/2010101716285514.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;注：Function构造任何函数对象的过程都是一样的，所以说不管是String,Boolean,Number等内置对象，还是用户自定义对象,其构造过程都和上图一样。这里String只是一个代表而矣！&lt;/p&gt;&lt;p&gt;图中可以看出constructor是Function在创建函数对象时产生的，也正如'prototype与constructor的关系'中讲的那样，constructor是函数对象prototype链中的一个属性。即String=== String.prototype.constructor。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;我还想用一段代码来证明一下,理论是正确的：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;function Person(){}&lt;br/&gt;var p = new Person();&lt;br/&gt;alert(p.constructor);//Person&lt;br/&gt;alert(Person.prototype.constructor);//Person&lt;br/&gt;alert(Person.prototype.hasOwnProperty('constructor'));//true&lt;br/&gt;&lt;br/&gt;alert(Person.prototype.isPrototypeOf(p));//true&lt;br/&gt;alert(Object.prototype.isPrototypeOf(p));//true&lt;br/&gt;alert(Person.prototype == Object.prototype);//false&lt;/div&gt;&lt;p&gt;&lt;span style="font-size: 10pt;"&gt;到现在，你会发现这和前面《原型链的实现原理》中的默认prototype指向Object.prototype有冲突，显然当时的理论不是很全面。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 10pt;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 18pt;"&gt;&lt;strong&gt;特别的Object&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 10pt;"&gt;用心的读者可能会提出这样一问题,你这一套理论并不能适用于Object。因为以下的代码和你上面的理论是冲突的：&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 10pt;"&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;alert(Object.prototype.hasOwnProperty('constructor'));//true&lt;br/&gt;alert(Object.prototype.hasOwnProperty('isPrototypeOf'));//true,如果按上面的理论，这里应该返回false&lt;/div&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 10pt;"&gt;真的是这样吗？不是！那我们来看一下特殊的Object是如何处理的：&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 10pt;"&gt;&lt;img src="http://pic002.cnblogs.com/images/2010/138960/2010101716251570.png" alt="" /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 10pt;"&gt;你会发现，这图的原理和上面一张图的原理是一样的。这就能正确解释Object.prototype.hasOwnProperty('isPrototypeOf')为true!&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 18pt;"&gt;&lt;strong&gt;constructor探究&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;function Animal(){}&lt;br/&gt;&lt;br/&gt;function Person(){}&lt;br/&gt;&lt;br/&gt;var person = new Person();&lt;br/&gt;alert(person.constructor); //Person&lt;br/&gt;&lt;/div&gt;&lt;p&gt;根据上一节的内容，你能正确的理解这段代码的结果吗？思考后，看一下其内存表示：&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2010/138960/2010101715300756.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;这张图明确有表明了Function构造Animal和Person的过程。同时也显示了实例person与Person的关系。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;再深入一点，代码如下：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;function Animal(){}&lt;br/&gt;function Person(){}&lt;br/&gt;&lt;br/&gt;Person.prototype = new Animal();&lt;br/&gt;&lt;br/&gt;var person = new Person();&lt;br/&gt;alert(person.constructor); //Animal&lt;/div&gt;&lt;p&gt;这个时候，person的构造函数成了Animal，怎么解释？&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2010/138960/2010101715344413.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;注：图中的虚线表示Person默认的prototype指向(只作参考的作用)。但是我们将Person.prototype指向了new Animal。&lt;/p&gt;&lt;p&gt;此时，Person的prototype指向的是Animal的实例，所以person的constructor为Animal这个构造函数。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;结论：constructor的原理非常简单，就是在对象的原型链上寻找constructor属性。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;注:如果你无法正确理解本文内容，请回顾前面章节的内容。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/fool/aggbug/1853126.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/fool/archive/2010/10/16/1853126.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/fool/archive/2010/10/15/1851856.html</id><title type="text">理解Javascript_10_对象模型</title><summary type="text">什么都不想说，一段代码两张图，解释一切。注：在此之前请阅读前面的系列博文对象模型图片来自于：http://www.cnblogs.com/riccc红色虚线表示隐式Prototype链。这张对象模型图中包含了太多东西，不少地方需要仔细体会，可以写些测试代码进行验证。彻底理解了这张图，对JavaScript语言的了解也就差不多了。下面是一些补充说明:1. 图中有好几个地方提到build-in Fun...</summary><published>2010-10-14T19:13:00Z</published><updated>2010-10-14T19:13:00Z</updated><author><name>笨蛋的座右铭</name><uri>http://www.cnblogs.com/fool/</uri></author><link rel="alternate" href="http://www.cnblogs.com/fool/archive/2010/10/15/1851856.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/fool/archive/2010/10/15/1851856.html"/><content type="html">&lt;p&gt;什么都不想说，一段代码两张图，解释一切。注：在此之前请阅读前面的系列博文&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 18pt;"&gt;&lt;strong&gt;对象模型&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2010/138960/2010101502424355.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 8pt;"&gt;图片来自于：&lt;a href="http://www.cnblogs.com/riccc"&gt;http://www.cnblogs.com/riccc&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;红色虚线表示隐式Prototype链。&lt;br /&gt;这张对象模型图中包含了太多东西，不少地方需要仔细体会，可以写些测试代码进行验证。彻底理解了这张图，对JavaScript语言的了解也就差不多了。下面是一些补充说明:&lt;br /&gt;1. 图中有好几个地方提到build-in Function constructor，这是同一个对象，可以测试验证:&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;//Passed in FF2.0, IE7, Opera9.25, Safari3.0.4&lt;br/&gt;Function==Function.constructor //result: true&lt;br/&gt;Function==Function.prototype.constructor //result: true&lt;br/&gt;Function==Object.constructor //result: true&lt;br/&gt;//Function also equals to Number.constructor, String.constructor, Array.constructor, RegExp.constructor, etc.&lt;br/&gt;function fn(){}&lt;br/&gt;Function==fn.constructor //result: true&lt;/div&gt;&lt;p&gt;&lt;span style="font-family: 宋体;"&gt;&lt;span style="font-size: 12pt;"&gt;&lt;span style="font-size: 12pt;"&gt;这说明了几个问题: Function指向系统内置的函数构造器(build-in Function constructor)；Function具有自举性；系统中所有函数都是由Function构造。&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: 宋体;"&gt;&lt;span style="font-size: 12pt;"&gt;&lt;span style="font-size: 12pt;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: 宋体;"&gt;&lt;span style="font-size: 12pt;"&gt;&lt;span style="font-size: 12pt;"&gt;2. 左下角的obj1, obj2...objn范指用类似这样的代码创建的对象: function fn1(){}; var obj1=new fn1();这些对象没有本地constructor方法，但它们将从Prototype链上得到一个继承的constructor方法，即fn.prototype.constructor，从函数对象的构造过程可以知道，它就是fn本身了。&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 12pt;"&gt;&lt;span style="font-size: 12pt;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;p&gt;&lt;div&gt;&lt;span style="font-family: 宋体; font-size: 12pt;"&gt;&lt;br /&gt;3.右下角的obj1, obj2...objn范指用类似这样的代码创建的对象: var obj1=new Object();或var obj1={};或var obj1=new Number(123);或obj1=/\w+/;等等。所以这些对象Prototype链的指向、从Prototype链继承而来的 constructor的值(指它们的constructor是build-in Number constructor还是build-in Object constructor等)等依赖于具体的对象类型。另外注意的是，var obj=new Object(123);这样创建的对象，它的类型仍然是Number，即同样需要根据参数值的类型来确定。同样它们也没有本地constructor，而是从Prototype链上获得继承的constructor方法，即build-in *** constructor，具体是哪一个由数据类型确定。&lt;/span&gt;&lt;/div&gt;&lt;/p&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: 宋体; font-size: 12pt;"&gt;&lt;p&gt;&lt;div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;/div&gt;&lt;/p&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: 宋体;"&gt;&lt;span style="font-size: 12pt;"&gt;&lt;p&gt;&lt;span style="font-size: 18pt;"&gt;&lt;strong&gt;示例代码&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;//自定义对象代表,对应Javascript Object Model中的use defined functions&lt;br/&gt;function Foo(){}&lt;br/&gt;//自定义对象创建的对象实例的代表，对应Javascript Object Model中的objects that created by user defined functions&lt;br/&gt;var foo = new Foo();&lt;br/&gt;&lt;br/&gt;//String内置函数代表&lt;br/&gt;//str为内置函数创建的对象实例的代表，对应Javascript Object Model中的objects that created by build-in constructors&lt;br/&gt;var str = new String("string");&lt;/div&gt;&lt;p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 18pt;"&gt;&lt;strong&gt;内存展现&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;/span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: 宋体;"&gt;&lt;img src="http://pic002.cnblogs.com/images/2010/138960/2010101503072426.png" alt="" /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: 宋体;"&gt;你会发现，它和《理解Javascript_09_Function与Object》中的内存分析图是一样的，为什么呢？在《数据模型》中提到过，内置对象都可以看作是函数的派生类型，例如Number instanceof Function为true，Number instanceof Object为true。在这个意义上，可以将它们跟用户定义的函数等同看待。所以内置对象和自定义对象的创建流程是一样的。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: 宋体;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: 宋体;"&gt;在篇博文是在理解了《Function与Object》的基础上写的，因此要理解本文必须理解Function与Object的关系！&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: 宋体;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: 宋体;"&gt;最后写一点感言：令人发狂的理论！&lt;/span&gt;&lt;/p&gt;&lt;div id="_mcePaste" class="mcePaste" style="position: absolute; width: 1px; height: 1px; overflow: hidden; top: 0px; left: -10000px;"&gt;﻿&lt;/div&gt;&lt;img src="http://www.cnblogs.com/fool/aggbug/1851856.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/fool/archive/2010/10/15/1851856.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/fool/archive/2010/10/15/1851851.html</id><title type="text">理解Javascript_09_Function与Object</title><summary type="text">在《理解Javascript_08_函数对象》中讲解了很多函数对象的问题，同时也留下了许多疑问，今天让我们来解答部分问题。注：理论过于深入，本人不改保证所有的理论都是正确的，但经过多方测试还未发现实际代码与理论冲突的问题。如有错误，望高人指点！Function首先回顾一下函数对象的概念，函数就是对象,代表函数的对象就是函数对象。所有的函数对象是被Function这个函数对象构造出来的。也就是说...</summary><published>2010-10-14T18:03:00Z</published><updated>2010-10-14T18:03:00Z</updated><author><name>笨蛋的座右铭</name><uri>http://www.cnblogs.com/fool/</uri></author><link rel="alternate" href="http://www.cnblogs.com/fool/archive/2010/10/15/1851851.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/fool/archive/2010/10/15/1851851.html"/><content type="html">&lt;p&gt;在《理解Javascript_08_函数对象》中讲解了很多函数对象的问题，同时也留下了许多疑问，今天让我们来解答部分问题。&lt;/p&gt;&lt;p&gt;注：理论过于深入，本人不改保证所有的理论都是正确的，但经过多方测试还未发现实际代码与理论冲突的问题。如有错误，望高人指点！&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 18pt;"&gt;&lt;strong&gt;Function&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;首先回顾一下函数对象的概念，函数就是对象,代表函数的对象就是函数对象。所有的函数对象是被Function这个函数对象构造出来的。也就是说，Function是最顶层的构造器。它构造了系统中所有的对象，包括用户自定义对象，系统内置对象，甚至包括它自已。这也表明Function具有自举性(自已构造自己的能力)。这也间接决定了Function的[[call]]和[[constructor]]逻辑相同。&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;function Foo() {};&lt;br/&gt;var foo = new Foo();&lt;br/&gt;//Foo为foo的构造函数&lt;br/&gt;alert(foo instanceof Foo); // true&lt;br/&gt;//但是Function并不是foo的构造函数&lt;br/&gt;alert(foo instanceof Function); // false&lt;br/&gt;//Function为Foo的构造函数&lt;br/&gt;alert(Foo instanceof Function);//true&lt;/div&gt;&lt;p&gt;上面的代码解释了foo和其构造函数Foo和Foo的构造函数Function的关系。(具体原理请参见Function与Object的内存关系图)&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 18pt;"&gt;&lt;strong&gt;Object　&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;对于Object它是最顶层的对象，所有的对象都将继承Object的原型，但是你也要明确的知道Object也是一个函数对象，所以说Object是被Function构造出来的。（关于Object并没有太多的理论）&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 18pt;"&gt;&lt;strong&gt;Function与Object&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;这是本文的重点，非常重要！&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;alert(Function instanceof Function);//true &lt;br/&gt;alert(Function instanceof Object);//true&lt;br/&gt;alert(Object instanceof Function);//true &lt;br/&gt;   &lt;br/&gt;function Foo() {};&lt;br/&gt;var foo = new Foo();&lt;br/&gt;alert(foo instanceof Foo); // true&lt;br/&gt;alert(foo instanceof Function); // false&lt;br/&gt;alert(foo instanceof Object); // true&lt;br/&gt;alert(Foo instanceof Function); // true&lt;br/&gt;alert(Foo instanceof Object); // true&lt;/div&gt;&lt;p&gt;你能理解这些答案吗？那恭喜你，Javascript语言的本质你已经理解了。&lt;/p&gt;&lt;p&gt;那么让我们来看一下Object与Function实际的关系吧：&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2010/138960/2010101501490224.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;在你看图之前，请先阅读函数对象与instanceof原理两篇文章，要不然内存图很难理解。&lt;/p&gt;&lt;p&gt;在这，我对内存图做一点说明：在函数对象一文中提到了函数对象的构造过程，在本文中提到Function为自举性的，所以说函数对象Foo的构造过程和函数对象Function的构造过程是一样的。所以在图中给于高亮显示，我用'|'来分隔来表示它们的构造过程相同。根据instanceof的理论，和内存图，可以将上面的语句都推导出正确的结果。在此我们不一一讲述了，读者自已体会吧。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;如果你不能理解这张复杂的内存图的话，可以看下面的说明图来帮助理解：&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2010/138960/2010101501362129.jpg" alt="" /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;注：代码的实际执行流程并不完全像这张图上描述的那样，也就是说这张图是有问题的(可以说是错误的),它无法解释为什么Function instanceof Function 为true。 但是它易于理解Function与Object的关系。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/fool/aggbug/1851851.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/fool/archive/2010/10/15/1851851.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/fool/archive/2010/10/14/1851017.html</id><title type="text">理解Javascript_08_函数对象</title><summary type="text">如果你无法理解博文在讲什么，请回顾前面的系列博文。文章比较深入，如有不对之处，望请指正，谢谢。函数对象首先，大家得明确一个概念：函数就是对象,代表函数的对象就是函数对象。既然是对象，那它又是被谁构造出来的呢？下面我们来看一段描述:JavaScript代码中定义函数，或者调用Function创建函数时，最终都会以类似这样的形式调用Function函数:var newFun=Function(funA...</summary><published>2010-10-14T02:38:00Z</published><updated>2010-10-14T02:38:00Z</updated><author><name>笨蛋的座右铭</name><uri>http://www.cnblogs.com/fool/</uri></author><link rel="alternate" href="http://www.cnblogs.com/fool/archive/2010/10/14/1851017.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/fool/archive/2010/10/14/1851017.html"/><content type="html">&lt;p&gt;&lt;span style="font-size: 12pt;"&gt;如果你无法理解博文在讲什么，请回顾前面的系列博文。&lt;span style="font-size: 12pt;"&gt;文章比较深入，如有不对之处，望请指正，谢谢。&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 12pt;"&gt;&lt;span style="font-size: 12pt;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 18pt;"&gt;&lt;strong&gt;函数对象&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;首先，大家得明确一个概念：函数就是对象,代表函数的对象就是函数对象。既然是对象，那它又是被谁构造出来的呢？下面我们来看一段描述:JavaScript代码中定义函数，或者调用Function创建函数时，最终都会以类似这样的形式调用Function函数:var newFun=Function(funArgs, funBody); 。由此可知函数对象是由Function这个函数对象构造出来的。&lt;/p&gt;&lt;p&gt;注：Function对象本身也是一个函数，因此它也一个函数对象。关于Function的深入理解，请见后续博文。&lt;/p&gt;&lt;p&gt;正面我们来看一段代码：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;//定义方式一&lt;br/&gt;function func(x) {&lt;br/&gt;    alert(x);&lt;br/&gt;}&lt;br/&gt;&lt;br/&gt;//定义方式二&lt;br/&gt;var func = function(x) {&lt;br/&gt;    alert(x);&lt;br/&gt;};&lt;br/&gt;&lt;br/&gt;//实际执行&lt;br/&gt;var func = new Function(&amp;ldquo;x&amp;rdquo;, &amp;ldquo;alert(x);&amp;rdquo;);&lt;br/&gt;&lt;/div&gt;&lt;p&gt;通过上面的代码可知，函数func无非是由Function对象接收两个参数后构造出来的而矣！&lt;/p&gt;&lt;p&gt;注：关于定义方式一与定义方式二的区别，请见后续博文&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 18pt;"&gt;&lt;strong&gt;函数对象的创建过程&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;函数对象详细创建步骤如下：&lt;/p&gt;&lt;p&gt;1. 创建一个build-in object对象fn&lt;/p&gt;&lt;p&gt;2. 将fn的内部[[Prototype]]设为Function.prototype&lt;br /&gt;3. 设置内部的[[Call]]属性,它是内部实现的一个方法,处理函数调用的逻辑。（简单的理解为调用函数体）&lt;/p&gt;&lt;p&gt;4. 设置内部的[[Construct]]属性，它是内部实现的一个方法，处理逻辑参考对象创建过程。(简单的理解为创建对象《理解Javascript_06_理解对象的创建过程》一文)&lt;/p&gt;&lt;p&gt;5. 设置fn.length为funArgs.length，如果函数没有参数，则将fn.length设置为0&lt;br /&gt;6. 使用new Object()同样的逻辑创建一个Object对象fnProto&lt;br /&gt;7. 将fnProto.constructor设为fn&lt;br /&gt;8. 将fn.prototype设为fnProto&lt;br /&gt;9. 返回fn&lt;/p&gt;&lt;p&gt;步骤1跟步骤6的区别为，步骤1只是创建内部用来实现Object对象的数据结构(build-in object structure)，并完成内部必要的初始化工作，但它的[[Prototype]]、[[Call]]、[[Construct]]等属性应当为 null或者内部初始化值，即我们可以理解为不指向任何对象(对[[Prototype]]这样的属性而言)，或者不包含任何处理(对 [[Call]]、[[Construct]]这样的方法而言)。步骤6则将按照《理解Javascript_06_理解对象的创建过程》创建一个新的对象，它的 [[Prototype]]等被设置了。&lt;br /&gt;从上面的处理步骤可以了解，任何时候我们定义一个函数，它的prototype是一个Object实例，这样默认情况下我们创建自定义函数的实例对象时，它们的Prototype链将指向Object.prototype。&lt;/p&gt;&lt;p&gt;注：Function一个特殊的地方，是它的[[Call]]和[[Construct]]处理逻辑一样。深层次的原因将在后续博文中介绍。&lt;/p&gt;&lt;p&gt;下面我们写一些用例脚本来测试一下上面的理论：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;function Animal(){&lt;br/&gt;}&lt;br/&gt;alert(Animal.length);//0&lt;br/&gt;&lt;br/&gt;var dog = new Animal();function Person(name,age){&lt;br/&gt;}&lt;br/&gt;alert(Person.length);//2&lt;/div&gt;&lt;p&gt;这个JS证明了步骤5的正确性。最后，还是来看一下函数对象的内存图,简单起见，内存图只描述了Animal的构造过程：&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2010/138960/2010101409535762.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;来自于一个整体的分析图：&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2010/138960/2010101410172219.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;图片本身已经能解释很多很多的问题了，结合前面instanceof原理，对象构造原理，原型链原理，自已去体会吧，我就不多说什么了。&lt;/p&gt;&lt;p&gt;其实上Function对象是一个很奇妙的对象，它与Object的关系更是扑朔迷离,我将在《理解Javascript_09_Function与Object》中解释这一切。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;最后的声明：理论过于复杂，我不改保证其正确性。但经过多方的测试，还未发现理论与实际冲突的地方。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/fool/aggbug/1851017.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/fool/archive/2010/10/14/1851017.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry></feed>
