84669 人が学習中
152542 人が学習中
20005 人が学習中
5487 人が学習中
7821 人が学習中
359900 人が学習中
3350 人が学習中
180660 人が学習中
48569 人が学習中
18603 人が学習中
40936 人が学習中
1549 人が学習中
1183 人が学習中
32909 人が学習中
为什么第一个图里的函数实例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