We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
JS基础知识温习。
分3个阶段:
本阶段就是书本中所说的Hoisting,包括:形参变量创建、函数体内变量提升创建 和 函数申明创建。
形参变量创建
函数体内变量提升创建
函数申明创建
就是先把函数中所有的变量或者声明的函数名都先定义好,空间都开辟好。
关于准备阶段的特别说明:
这里装载填充的数据包括:形参 和 申明的函数体。
形参
申明的函数体
也许你要问了,为什么一般的变量只是拿到前面定义好,此时值是 undefined,填充数据需要等到执行那一行才进行,而 形参 和 申明的函数 在代码执行前就要装载好呢?
undefined
申明的函数
答: 我个人的理解是(有更专业的解释,欢迎批评指正):
函数申明
关于装载的特别说明:
函数形参
通过上面的2个阶段,大家就知道,当函数真正一行行开始执行的时候,其实有些值已经存在了,并不是大家想象中的全部为 undefined。
本阶段就是纯粹的执行代码了,执行就包括了:变量赋值、对象调用等等。
但是本阶段其实JS引擎还做了另外一件事情,就是:代码检查。如果报错了,会直接中断程序,除非使用 try/catch 捕获。
代码检查
try/catch
function test() { console.log('1、a=',a); var a = b = 123; console.log('2、a=',a); console.log('3、b=',b); }; test(); console.log('4、b=',b); console.log('5、a=',a);
变量提升(Hoisting),这一步执行后,实际的代码变为:
function test() { var a; console.log('1、a=',a); b=123; a=b; console.log('2、a=',a); console.log('3、b=',b); }; test(); console.log('4、b=',b); console.log('5、a=',a);
补充说明: 关于 var a = b = 123 的解释,请移步: JS解惑-连等表达式
var a = b = 123
由于函数没有形参和函数申明,所以该步直接跳过。
//1 var a; //2 console.log('1、a=',a); //3 b=123; //4 a=b; //5 console.log('2、a=',a); //6 console.log('3、b=',b);
1、a= undefined
window
2、a= 123
3、b= 123
//7 console.log('4、b=',b); //8 console.log('5、a=',a);
4、b= 123
补充说明: 错误类型为 ReferenceError 引用错误,也就是说系统根本不知道哪个对象或者函数下面的属性a,所以会报这个错误。如果这时候你打印 window.a,那么结果将是 undefined 而不会报错。
ReferenceError
window.a
function test(a) { console.log('1、a=',a); var a=123; console.log('2、a=',a); function a(){}; console.log('3、a=',a); }; test(1);
定义变量a,代码变为:
function test(a) { var a; console.log('1、a=',a); a=123; console.log('2、a=',a); function a(){}; console.log('3、a=',a); };
装载完毕后,代码变为:
function test(a) { var a = function(){}; console.log('1、a=',a); a=123; console.log('2、a=',a); console.log('3、a=',a); };
看到第二步装载完毕后的代码,那么结果也就很清楚了。
function test(a,b){ console.log('1、a=',a); c=0; var c; console.log('2、c=',c); a=3; b=2; console.log('3、b=',b); function b(){}; function d(){}; console.log('4、b=',b); }; test(1);
找到所有的局部变量,注意包含形参中的,包括:
于是原函数就变为:
function test(a,b){ var a; var b; var c; var d; console.log('1、a=',a); c=0; console.log('2、c=',c); a=3; b=2; console.log('3、b=',b); function b(){}; function d(){}; console.log('4、b=',b); }; test(1);
注意装载的顺序:形参先装载,其次是函数声明,而且函数申明会覆盖已定义的变量。
于是函数就变成为:
function test(){ var a=1; var b=function(){};//实参并没有传第2个参数,默认为undefined;但后来又被函数申明覆盖了。 var c=undefined;//没有地方为其赋值 var d=function(){}; console.log('1、a=',a); c=0; console.log('2、c=',c); a=3; b=2; console.log('3、b=',b); console.log('4、b=',b); }; test(1);
先看看装载后的函数的执行结果:
所以,其实这类题目最难的就是分析阶段,包括:(准备、装载),一旦这2个阶段处理好,执行阶段基本就是直接打印结果了。
最后一道带一些逻辑,可能会影响到分析阶段的。
function test(a,b){ console.log('2、b=',b); if(a){ var b=100; }; console.log('3、b=',b); c=456; console.log('4、c=',c); }; var a; console.log('1、a=',a); test(); a=10; console.log('5、a=',a); console.log('6、c=',c);
这类题目,先不用管函数体外的代码,因为函数准备和装载,跟外部代码怎么执行没关系。
对于变量前没有var申明的,说明是全局变量,不用理会。
于是代码变为:
function test(a,b){ var a; var b; console.log('2、b=',b); if(a){ b=100; }; console.log('3、b=',b); c=456; console.log('4、c=',c); }; var a; console.log('1、a=',a); test(); a=10; console.log('5、a=',a); console.log('6、c=',c);
装载阶段依然只管函数体内。
function test(){ var a=undefined; var b=undefined; console.log('2、b=',b); if(a){ b=100; }; console.log('3、b=',b); c=456; console.log('4、c=',c); }; var a; console.log('1、a=',a); test(); a=10; console.log('5、a=',a); console.log('6、c=',c);
先增加一个行号:
function test(){ var a=undefined; var b=undefined; //7 console.log('2、b=',b); if(a){ b=100; }; //8 console.log('3、b=',b); c=456; //9 console.log('4、c=',c); }; //1 var a; //2 console.log('1、a=',a); //3 test(); //4 a=10; //5 console.log('5、a=',a); //6 console.log('6、c=',c);
通过以上讲解,中间穿插了一些基础知识,这里跟大家简要总结分享下。
函数的定义有三种形式:
function fun1(){};
函数表达式
var fun2 = function(){};
构造函数Function
var fun3 = new Function("a", "b", "return a * b");
就是将函数体内的 局部变量 和 函数申明 放到函数的最前面定义。
局部变量
请移步: JS解惑-连等表达式
function fun4(var1,var2){//函数结构体括号内的变量,就叫做形参。 //TODO }; fun4('abc',123);//调用函数时,实际传的值就叫做实参。
准备
(全文完)
The text was updated successfully, but these errors were encountered:
sunmaobin
No branches or pull requests
js解惑-函数执行顺序
背景
JS基础知识温习。
函数解析原理
分3个阶段:
准备
本阶段就是书本中所说的Hoisting,包括:
形参变量创建
、函数体内变量提升创建
和函数申明创建
。就是先把函数中所有的变量或者声明的函数名都先定义好,空间都开辟好。
关于准备阶段的特别说明:
装载
这里装载填充的数据包括:
形参
和申明的函数体
。也许你要问了,为什么一般的变量只是拿到前面定义好,此时值是
undefined
,填充数据需要等到执行那一行才进行,而形参
和申明的函数
在代码执行前就要装载好呢?答: 我个人的理解是(有更专业的解释,欢迎批评指正):
形参
是外部传进来的,是函数在执行前就已经知道的数据,所以直接就装载上;而对于函数中普通的变量,受限于JS解析顺序的机制影响,只能等到具体执行到那一行时才能知道。函数申明
为什么要放到前面去呢?这应该也是JS的策略吧,不然函数表达式(var xxx=fn)为啥就没这个待遇呢?关于装载的特别说明:
函数形参
>函数申明
;执行
通过上面的2个阶段,大家就知道,当函数真正一行行开始执行的时候,其实有些值已经存在了,并不是大家想象中的全部为
undefined
。本阶段就是纯粹的执行代码了,执行就包括了:变量赋值、对象调用等等。
但是本阶段其实JS引擎还做了另外一件事情,就是:
代码检查
。如果报错了,会直接中断程序,除非使用try/catch
捕获。示例一
分析
第一步:准备
变量提升(Hoisting),这一步执行后,实际的代码变为:
补充说明: 关于
var a = b = 123
的解释,请移步: JS解惑-连等表达式第二步:装载
由于函数没有形参和函数申明,所以该步直接跳过。
第三步:执行
undefined
;1、a= undefined
;window
所对应的对象下面创建属性b,并且为其赋值为123,window.b=123;2、a= 123
;3、b= 123
;最后:函数执行完后,局部变量立即销毁,全局变量仍然保留。
4、b= 123
;最终结果
补充说明: 错误类型为
ReferenceError
引用错误,也就是说系统根本不知道哪个对象或者函数下面的属性a,所以会报这个错误。如果这时候你打印window.a
,那么结果将是undefined
而不会报错。示例二
分析
第一步:准备
定义变量a,代码变为:
第二步:装载
装载完毕后,代码变为:
第三步:执行
看到第二步装载完毕后的代码,那么结果也就很清楚了。
最终结果
示例三
分析
准备
找到所有的局部变量,注意包含形参中的,包括:
于是原函数就变为:
装载
注意装载的顺序:形参先装载,其次是函数声明,而且函数申明会覆盖已定义的变量。
于是函数就变成为:
执行
先看看装载后的函数的执行结果:
所以,其实这类题目最难的就是分析阶段,包括:(准备、装载),一旦这2个阶段处理好,执行阶段基本就是直接打印结果了。
最终结果
示例四
最后一道带一些逻辑,可能会影响到分析阶段的。
分析
准备
这类题目,先不用管函数体外的代码,因为函数准备和装载,跟外部代码怎么执行没关系。
对于变量前没有var申明的,说明是全局变量,不用理会。
于是代码变为:
装载
装载阶段依然只管函数体内。
执行
先增加一个行号:
最终结果
彩蛋
通过以上讲解,中间穿插了一些基础知识,这里跟大家简要总结分享下。
函数的定义
函数的定义有三种形式:
函数申明
函数表达式
构造函数Function
变量提升(Hoisting)
就是将函数体内的
局部变量
和函数申明
放到函数的最前面定义。连等表达式
请移步: JS解惑-连等表达式
什么是形参、实参
GO和VO对象是什么
准备
阶段时,用来存放准备的数据的,这些数据包括3类:形参、变量和函数声明。window
对象。参考
(全文完)
The text was updated successfully, but these errors were encountered: