今天在群里看到一个问题,让我纠结了好一会。下面是我的分析,感觉里面还有很多问题,关于作用域还是不太理解,希望大家看到问题第一时间反馈给我,看到实在受不了的地方说几句都没关系,谢谢。

  请看题:

1.对象字面量中fn1函数是立即执行的函数表达式。

            $(function(){
var number = 2;
var obj = {
number: 4,
fn1: (function(){
this.number *= 2;
number = number*2;
var number = 3;
return function(){
this.number *= 2;
number *= 3;
alert(number);
}
})()
};
var f = obj.fn1;
alert(number); /* 2 */
f(); /* 9 */
obj.fn1(); /* 27 */ /* 因为是自执行的,number值是可以保存下来的 */
alert(window.number); /* NaN */
          alert(obj.number); /* 8 */
}) </script>

  输出2, 9,27, NaN, 8。

  分析:

  首先看fn1这个函数,是立即执行的函数表达式,所以var f = obj.fn1的时候,已经访问fn1函数下的内容了。在立即执行函数表达式fn1中,this.number为NaN,因为在此访问不到自己的属性和方法(这个我也说不太清楚为什么,求解……);number = number * 2为NaN,因为number是undefined,这是根据预解析的缘故,会先定义var number; number= number *2; number = 3。接下来又定义了var number = 3,在该作用域中和内部作用域中,number暂时都是为3的。在return function(){}中,因为外部立即执行的函数表达式,所以this.number是有效的(求解……),number = number *3是根据外部作用域number值决定的。

  alert(number);输出2,因为预解析的缘故。

  f();输出9,因为外部number为3,所以3*3 = 9。

  obj.fn1();输出27,因为是立即执行函数,所有具有保存变量值的作用,number值是9,再用9*3 = 27,。

  alert(window.number);输出NaN,因为是在加载后输出,要让window.number有效,只能在局部作用域内才可以。

  alert(obj.number);输出8,因为fn1中this.number失效,return function()中this.number有用,所以只执行return 函数中的this.number *= 2。

2.对象字面量中fn1函数不是立即执行的函数表达式

            $(function(){
var number = 2;
var obj = {
number: 4,
fn1: function(){
this.number *= 2;
number = number*2;
var number = 3;
return function(){
this.number *= 2;
number *= 3;
alert(number);
}
}
};
var f = obj.fn1();
alert(number); /* 2 */
f(); /* 9 */
obj.fn1()(); /* 9 */ /* 这个和上面作用域不一样了,因为不是表达式,不是立即执行的,在新的作用域又全都是新的 */
alert(window.number); /* NaN */
alert(obj.number); /* 16 */ })

  输出2, 9, 9, NaN,16。

  分析:

  首先看fn1这个函数,它是一个函数引用(需调用才会执行),所以var f = obj.fn1()(后面需接括号)的时候,已经访问fn1函数下的内容了。在立即执行函数表达式fn1中,this.number为有效的,在一般函数可以访问到自己的属性和方法;number = number * 2为NaN,因为number是undefined,这是根据预解析的缘故,会先定义var number; number= number *2; number = 3。接下来又定义了var number = 3。在return function(){}中,因为外部函数为一般函数,所以this.number是无效的(求解……),number = number *3是根据外部作用域number值决定的。

  alert(number);输出2,因为预解析的缘故。

  f();输出9,因为外部number为3,所以3*3 = 9。

  obj.fn1()();输出9,因为它和f()不在同一作用域中,它调用了fn1()初始化number = 3,后面再输出一个obj.fn1()()还是为9。

  alert(window.number);输出NaN,因为是在加载后输出,要让window.number有效,只能在局部作用域内才可以。

  alert(obj.number);输出16,因为fn1中this.number有用,return function()中this.number失效,所以只执行fn1函数中的this.number *= 2。

对于(function(){}())和function(){}实例的作用域分析(里面有很多问题……)的更多相关文章

  1. function foo(){}、(function(){})、(function(){}())等函数区别分析

    前面一段时间,看到(function(){}),(function(){}())这些函数就犯晕,不知道它到底是什么意思,为什么函数外要加小括号,函数后要加小括号,加和不加到底有什么区别……一直犯迷糊, ...

  2. 转载 +function ($) { "use strict";}(window.jQuery);全面分析

    转载 https://www.cnblogs.com/cndotabestdota/p/5664112.html +function ($) { "use strict";}(wi ...

  3. +function ($) { "use strict";}(window.jQuery);全面分析

    +function ($) { "use strict"; }(window.jQuery); 怎么理解? 匿名函数闭包 我们先来理一理函数表达式和函数声明的区别 函数表达式: 函 ...

  4. javascript 中function(){},new function(),new Function(),Function 摘录

    函数是JavaScript中很重要的一个语言元素,并且提供了一个function关键字和内置对象Function,下面是其可能的用法和它们之间的关系. function使用方式 var foo01 = ...

  5. Javacript中(function(){})() 与 (function(){}()) 区别 {转}

    这个问题可以从不同的角度来看,但从结果上来说 :他们是一样的.首先,如果从AST(抽象语法树)的角度来看,两者的AST是一模一样的,最终结果都是一次函数调用.因此,就解析器产生的结果论而言,两者是没有 ...

  6. function(){}、var fun=function(){}和function fun(){}的区别

    一.基本定义 1.函数声明:使用function声明函数,并指定函数名. function fun() { // ...... } 2.函数表达式:使用function声明函数,但未指定函数名,将匿名 ...

  7. 【javascript】javascript中function(){},function(){}(),new function(){},new Function()

    和java比起来,javascript真的是松散的无以复加,不过这也让我们在无聊之余,有精力去探讨一些复杂的应用,从而在开发之路上,获得一些新的想法. javascript中的类的构造 javascr ...

  8. javascript 中function(){}(),new function(),new Function(),Function

    和java比起来,javascript真的是松散的无以复加,不过这也让我们在无聊之余,有精力去探讨一些复杂的应用,从而在开发之路上,获得一些新的想法. javascript中的类的构造 javascr ...

  9. function,new function,Function,new Function 之间的区别

    测试一: var fud01 = function()  { var temp = 100; this.temp = 200; return temp + this.temp; } alert(typ ...

随机推荐

  1. 初探JAVA中I/O流(二)

    1.缓冲输入文件 FileReader BufferedReader FileReader可以直接对文件进行读操作.但是简化编程,加快读取速度,我们加入了缓冲机制,使用了BufferedReader. ...

  2. Linq之常见关键字

    目录 写在前面 系列文章 常见关键字 总结 写在前面 前面的几篇文章算是对linq的铺垫,从本篇开始将进行linq的语法及实践. 系列文章 Linq之Lambda表达式初步认识 Linq之Lambda ...

  3. 理解C#事件

    前面文章中介绍了委托相关的概念,委托实例保存这一个或一组操作,程序中将在某个特定的时刻通过委托实例使用这些操作. 如果做过GUI程序开发,可能对上面的描述会比较熟悉.在GUI程序中,单击一个butto ...

  4. WCF入门(7)

    前言 前段时间忙着驾照科目二的考试,都没有机会碰自己的电脑.说起来也是第一次参加这么没信心的考试,不过好在过了. 再打个广告吧,昨天终于把下载的WCF视频全部传到了QQ群共享里面,群号37819043 ...

  5. 每天一个linux命令(17):locate 命令

    locate 让使用者可以很快速的搜寻档案系统内是否有指定的档案.其方法是先建立一个包括系统内所有档案名称及路径的数据库,之后当寻找时就只需查询这个数据库,而不必实际深入档案系统之中了.在一般的 di ...

  6. Javascript继承机制的设计

    写软工作业时各种蛋疼:主要在于Javascript没有“子类”“父类”“接口”的概念,只能使用prototype来实现,看了下面一篇文章,感觉写得很不错~ http://www.ruanyifeng. ...

  7. hibernate事务

    hibernate事务 9.3 Hibernate的事务管理 事务(Transaction)是工作中的基本逻辑单位,可以用于确保数据库能够被正确修改,避免数据只修改了一部分而导致数据不完整,或者在修改 ...

  8. 【转】变量的声明和定义,从C到编译原理到C++,再到Java

    基础学了太久,时间一长有些东西就可能记得不太清楚,俗话说得好,"好记性不如烂笔头",所以把基础中的基础-变量的声明和定义,从C到编译原理到C++,再到Java用烂笔头记录下来 最早 ...

  9. OC基础--OC中类的声明与定义

    OC中设计一个类的步骤: 一.声明类: 1.用到的关键字--@interface 和 @end 2.类名 3.继承NSObject 4.属性 5.方法(行为,只需要声明) 二.实现(定义)类 1.用到 ...

  10. Java设计模式-备忘录模式(Memento)

    主要目的是保存一个对象的某个状态,以便在适当的时候恢复对象,个人觉得叫备份模式更形象些,通俗的讲下:假设有原始类A,A中有各种属性,A可以决定需要备份的属性,备忘录类B是用来存储A的一些内部状态,类C ...