84669 person learning
152542 person learning
20005 person learning
5487 person learning
7821 person learning
359900 person learning
3350 person learning
180660 person learning
48569 person learning
18603 person learning
40936 person learning
1549 person learning
1183 person learning
32909 person learning
为什么第一个图里的函数实例f1===f2就是假的。。第二个图里的函数实例f3===f4就是真的呢?还有什么是JS的函数实例呢?请大神指导一下小白
欢迎选择我的课程,让我们一起见证您的进步~~
每次执行aFunc的时候,会创建一个aFunc的新的执行环境。然后执行环境的作用域链就是aFunc的[[scope]]。与此同时,aFunc的活动对象也会push到执行环境的顶端。aFunc的活动对象包括var声明的局部变量、function声明的函数、以及aFunc的形参。这个MyFunc就是aFunc的活动对象,会在aFunc执行的时候创建。所以每次执行aFunc都会创建一个新的MyFunc。因此f1 与f2 是两个不同内存地址的函数,只是函数体(函数代码)相同而已。所以f1 == f2为false。
----------------------- 分割线 -----------------------
第二个图中,aFunc3的右侧是一个立即执行函数,aFunc3的值即是立即执行函数的返回值。在那个立即执行函数体内,注意return function (){return MyFunc;}这个匿名函数。这个匿名函数在创建的时候,会将作用域链保存在内部属性[[scope]]中,这个[[scope]]如图:然后匿名函数返回给了aFunc_3。每次执行aFunc_3(即刚才那个匿名函数),会创建一个执行环境,它内部属性[[scope]]会初始化给执行环境的作用域链,函数的活动对象再push到作用域链顶端,因为此函数内没有var声明的局部变量、function声明的函数以及参数,就为空。然后执行return MyFunc;,此时引擎会沿着作用域链往下找,找到MyFunc就返回。注意:这是一个顺着作用域链找标示符MyFunc的过程,并没有产生新的函数。所以所有aFunc_3执行后返回的函数都是当时那个MyFunc。因此f3 == f4为true。
return function (){return MyFunc;}
return MyFunc;
1)每次aFunc()执行后返回一个函数对象都是不同的,所以f1和f2不相同2)第二个片段aFunc_3指向一个立即执行函数执行后返回的函数,这个函数处在一个闭包环境中,每次执行总是返回闭包中的MyFunc函数,所以f3和f4是相同的3)JS中定义的任何一个函数-无论通过声明语法声明的还是通过函数表达式声明的-都是函数对象的实例,函数也是有原型的-Function
你仔细观察一下,第一个例子返回的是函数声明。也就是说,声明了2个同名函数,他们在堆内存中是不一样的。
第二个例子
因为aFunc_3有个函数自执行的括号,因此最后的结果是
var myFunc = function() {} aFunc_3 = function() { return myFunc; }
于是f3 === f4就很好理解了。他们指向了同一个函数。
看了一楼的答案之后百度了下,涨姿势了。。。现在我的理解,大概是这样的:
图1和图2的区别,主要就是关于JS的函数闭包和内存回收的问题。图1类似于:
var f1 = function(){ var f2 = function(){ }; return f2; };
或者考虑的更极端一点,这样:
f1 = function(){ f2 = function(){ }; return f2; };
无论如何,每次执行f1函数,f2必然都会被重新赋值为一个新的函数,于是函数的返回值不相等。
图2是这样的:
var f1 = function(){ var f2 = function(){ }; return function(){ return f2; } }();
更直观的理解就是:
var f1 = function(){ return f2; }
注意,每次执行f1函数,只执行这一句return f2;所以f2不是每次都变成新的函数。另外,因为f1的返回值持有了f2的引用,所以f2一直在内存里,不会被销毁。于是,函数的返回值都是f2。
你的第一个不相等是因为,你每执行一次函数,就返回了一个新的函数(也就是说内存上位置不同),所以肯定是不相等的,第二个相等是因为,这是一个自执行的函数,你的aFun3,也就是下面的这个函数
return function () { return MyFunc; }
所以你在执行aFun3返回的是同一个函数,也就是MyFun简单的可以将上面的两种情况等价为以下的两种情况:第一个:
var f1 = function () {}, f2 = function () {}, a = f1, b = f2; console.log(a === b); // 必然是false啊
第二个:
var f1 = function () {}, a = f1, b = f1; console.log(a === b); // true,a和b是指向同一函数
何必解释得那样图文并茂,反而让人看不懂
“js解释器在遇到函数定义的时候,会自动把函数和他可能使用的变量一起保存起来,构建一个闭包,这些变量将不会被内存回收器所回收。”
要搞清楚这个问题,涉及到几个概念作用域对象的比较方式闭包
第一张图每次调用,都会在外层函数的作用域中,重新定义内层函数并命名为MyFunc,然后return出来。所以,考虑到function也是个对象,代码简化为
function aFunc { var MyFunc = {} return MyFunc }
又因为对象的===实际是比的内存地址
{} === {} // false,因为两边并不是同一个{}
第二张图同理简化为下面的形式
var a = (function { var my = function (){} return function () { return my } })()
立即执行函数表达式(Immediately Invoke Function Expression)返回一个获取闭包内变量的函数此时,不妨再简化一下,所有作用域往上提一层,把my放在global,整个global可以看作一个大的“闭包”,a具有访问这个global“闭包”(作用域)内变量的能力
var my = function () {} var a = function () {return my}
显然,无论调用多少次a,返回的都是同一个my
每次执行aFunc的时候,会创建一个aFunc的新的执行环境。然后执行环境的作用域链就是aFunc的[[scope]]。
与此同时,aFunc的活动对象也会push到执行环境的顶端。
aFunc的活动对象包括var声明的局部变量、function声明的函数、以及aFunc的形参。
这个MyFunc就是aFunc的活动对象,会在aFunc执行的时候创建。
所以每次执行aFunc都会创建一个新的MyFunc。
因此f1 与f2 是两个不同内存地址的函数,只是函数体(函数代码)相同而已。
所以f1 == f2为false。
----------------------- 分割线 -----------------------
第二个图中,aFunc3的右侧是一个立即执行函数,aFunc3的值即是立即执行函数的返回值。
在那个立即执行函数体内,注意
return function (){return MyFunc;}
这个匿名函数。这个匿名函数在创建的时候,会将作用域链保存在内部属性[[scope]]中,这个[[scope]]如图:
然后匿名函数返回给了aFunc_3。
每次执行aFunc_3(即刚才那个匿名函数),会创建一个执行环境,它内部属性[[scope]]会初始化给执行环境的作用域链,函数的活动对象再push到作用域链顶端,因为此函数内没有var声明的局部变量、function声明的函数以及参数,就为空。
然后执行
return MyFunc;
,此时引擎会沿着作用域链往下找,找到MyFunc就返回。注意:这是一个顺着作用域链找标示符MyFunc的过程,并没有产生新的函数。
所以所有aFunc_3执行后返回的函数都是当时那个MyFunc。
因此f3 == f4为true。
1)每次aFunc()执行后返回一个函数对象都是不同的,所以f1和f2不相同
2)第二个片段aFunc_3指向一个立即执行函数执行后返回的函数,这个函数处在一个闭包环境中,每次执行总是返回闭包中的MyFunc函数,所以f3和f4是相同的
3)JS中定义的任何一个函数-无论通过声明语法声明的还是通过函数表达式声明的-都是函数对象的实例,函数也是有原型的-Function
你仔细观察一下,第一个例子返回的是函数声明。也就是说,声明了2个同名函数,他们在堆内存中是不一样的。
第二个例子
因为aFunc_3有个函数自执行的括号,因此最后的结果是
于是f3 === f4就很好理解了。他们指向了同一个函数。
看了一楼的答案之后百度了下,涨姿势了。。。
现在我的理解,大概是这样的:
图1和图2的区别,主要就是关于JS的函数闭包和内存回收的问题。
图1类似于:
或者考虑的更极端一点,这样:
无论如何,每次执行f1函数,f2必然都会被重新赋值为一个新的函数,于是函数的返回值不相等。
图2是这样的:
更直观的理解就是:
注意,每次执行f1函数,只执行这一句return f2;所以f2不是每次都变成新的函数。
另外,因为f1的返回值持有了f2的引用,所以f2一直在内存里,不会被销毁。
于是,函数的返回值都是f2。
你的第一个不相等是因为,你每执行一次函数,就返回了一个新的函数(也就是说内存上位置不同),所以肯定是不相等的,第二个相等是因为,这是一个自执行的函数,你的aFun3,也就是下面的这个函数
所以你在执行aFun3返回的是同一个函数,也就是MyFun
简单的可以将上面的两种情况等价为以下的两种情况:
第一个:
第二个:
何必解释得那样图文并茂,反而让人看不懂
“js解释器在遇到函数定义的时候,会自动把函数和他可能使用的变量一起保存起来,构建一个闭包,这些变量将不会被内存回收器所回收。”
要搞清楚这个问题,涉及到几个概念
作用域
对象的比较方式
闭包
第一张图
每次调用,都会在外层函数的作用域中,重新定义内层函数并命名为MyFunc,然后return出来。所以,考虑到function也是个对象,代码简化为
又因为对象的===实际是比的内存地址
第二张图
同理简化为下面的形式
立即执行函数表达式(Immediately Invoke Function Expression)返回一个获取闭包内变量的函数
此时,不妨再简化一下,所有作用域往上提一层,把my放在global,整个global可以看作一个大的“闭包”,a具有访问这个global“闭包”(作用域)内变量的能力
显然,无论调用多少次a,返回的都是同一个my