做预解释题的一点小方法和小技巧

时间:2022-11-30 02:39:54
 

    在JavaScript中的函数理解中预解释是一个比较难懂的话题。原理虽然简单,寥寥数言,但其内涵却有深意,精髓难懂。如何在轻松活跃的头脑中将它学会,现在针对我在学习中的一点小窍门给大家分享一下,希望能给大家一些帮助:

 

万事需遵循“原理”——“预解释”无节操和“this”指向:(可先看例题解析然后结合原理进行学习)

(感谢蕾蕾老师给归纳的预解释无节操原理:)

 

如果函数传参数则先于以下执行,就相当于在函数私有作用域下var了一个变量;根据作用域原理,私有作用域的权重永远大于父级作用域,当我私有作用域中有某个变量时,而我正好需要他时,私有作用域变量的值就是我所需要的;当私有作用域中没有时,而我有恰好需要它时,我就会沿着作用域链一级级的往上找。此时可得出子级可以用父级的变量,但父级不能访问子级的作用域,打个简单的比喻可能不太贴切,子孙能继承祖宗的财产,但祖宗不能继承子孙的财产,因为祖宗都没了,还怎么继承。

 

1. 只对等号左边带var的,声明但不定义
2. 自执行函数不会进行预解释,只有,执行到他的时候,声明+定义+调用同步完成
3. 已经声明过的不会进行重复声明,但会重新赋值;
4. return下面的语句虽然不会执行,但会进行预解释;
5. 函数的声明早于变量的声明
6. 在条件判断语句中,无论条件是否成立,都会进行预解释;
     不要在条件判断语句中写函数的定义阶段;否则,各大浏览器对其的兼容性不同
this指向:

 

1. 当一个元素身上的事件被触发的时候,会执行一个函数,函数中的this指向当前这个元素;
2. 自执行函数中的this,永远都是window
3. 回调函数中的this,一般都是windowsetInterval(函数名,1000)  ary.sort(function(){})
4. 当函数被调用的时候,看前面是否有".""."前面是谁,this就是谁;

原理阐述篇————实例小窍门篇:
1

1 (function f(){
2     function f(){ return 1; }
3     alert (f());
4     function f(){ return 2; }
5 })();

 


解析:此函数为自执行函数,观察函数,注意类似于function fn(){}这样的才是声明函数,像var f=function(){}b=function(){}这样的都不属于声明函数,前者属于变量的声明,

 

只有像声明函数那样的在函数才会进行预解释,此题中两个为需要声明的函数为同名函数,所以根据已经声明过的不会进行重复声明,但会重新赋值原理得到函数预解释为 function f(){ return 2; }
此时,当函数执行时

 

alert (f())的结果为2
2

 
var a=12;
function show(){
    alert(a);
    a=15;
}
show();
alert(a);

 



解析:此题为对作用域链的考察,先进行预解释,特别提示变量只有声明,函数既有声明还有定义,预解释了之后代码执行时就会自动跳过不执行,但var a=12,这相当于给变量重新赋值,因为任何变量进行预解释的初始值为

undefined;本题先对变量和函数进行预解释:var a=undefined;

function show(){
    alert(a);
    a=15;
}                     
 预解释完毕后,代码从上往下的执行,1. a=12; 2. function show(){alert(a);a=15}已经经过预解释不会执行; 3. show()进行函数的调用,alerta.当前作用域下没
a,就去父级作用域,a=124.接着执行a=15,任何在函数私有作用域下'变量'前面不带var的本身不属于当前作用域域,而是对全局作用域中全局变量的重新赋值,所
以此时相当于把全局变量中的a直接赋值为15; 5.最后在全局作用域下alert(a),只能访问自己的变量。所以a=15;

此题答案为 12,15

此题引申:

 
1 var a=12;
2 function show(){
3     alert(a);
4    var a=15;
5 }
6 show();
7 alert(a);

 



此时输出的结果为undefined12,你猜对了吗?切记私有作用域中的变量是以var为基准的,当然如果传参数例外,因为传参就相当于最先var,此题在show函数执行时,因为

 

里面有var,所以肯定有私有变量所以var a,接着alerta),大家应该没有忘记任何变量的预解释初始值为undefined,接着执行var a=15,此时相当于重新赋值,这里不用有疑问,因为代码
是从上往下执行,接着继续执行外面全局变量中的alerta)此时值为12,因为函数私有作用域中并没有改变全局变量的值。

再引申:

 
1 var a=12;
2 function show(a){
3     alert(a);
4    var a=15;
5 }
6 show(a);
7 alert(a);

 


此题结果应为12,12,此题相对于上一题做的改善是对函数进行了传参数处理,上面提过传参相当于最先进行var变量处理,所以在show函数执行时,私有变量a的最开始赋值就为12,在执行就相当于重新赋值

事已至此,咱们再引申一下:

 
1 var a=12;
2 function show(a){
3     alert(a);
4     a=15;
5 }
6 show(a);
7 alert(a);

 


此题结果应该为:12,15,此题主要关键点为全局变量的从新赋值:

那么大家肯定就更能做出这道题了:

 
1 alert(a);
2 var a = 12;
3 function show(a) {
4     alert(a);
5     var a = 15;
6     alert(a);
7 }
8 show(a);
9 alert(a);

 

 

此题结果为undefined1215,12

2:接下来我们来讨论一下变量和函数的一些关系:

 
1 function a() {
2     var b=10;
3     alert(b);
4 };
5 var a;
6 a();

 


解析:此题中变量和函数为同名,根据原理知识我们可以知道,函数的声明要优先于变量的声明,所以当同名时以函数优先,所以不难的出此题的答案为10;别急,你以为这么简单就完了,来开始做个小修改
引申一下:

 
1 function a() {
2     var b=10;
3     alert(b);
4 };
5 var a=6;
6 a();

 


解析:大家猜猜这道题的结果,如果你对上面的原理理解的不错的话,那么你应该很容易得出此题会报错,a is not defined; 确实函数占用了名称,当接下来执行var a=6,时,大家要注意了,只要变量
有等号就相当于重新赋值,但大家疑问来了,为啥会报错呢,请注意a的名字已经被函数占用,当你进行var a=6,时此时你又把a赋值给6,此时函数本身就犹如孤魂野鬼,没有名字,当最后调用啊a()我去哪找函数a,所以必须的必肯定会报错!!!
3

1 if("a" in window){
2     var a=15;
3 }
4 function fn() {
5     alert(a)
6 }
7 fn()

 

解析:此题考查的知识点为在条件判断语句中,无论条件是否成立,都会进行预解释,在此题中,大家也应该记住类似于“a” in window 都是正确的,所以起先会进行预解释 var a, 因为条件成立,进入
条件语句中会进行重新赋值,此时a=15;在函数中alerta,向上级作用域寻找a,结果为15

引申:

 
1 if(!"a" in window){
2     var a=15;
3 }
4 function fn() {
5     alert(a)
6 }
7 fn()

 


解析:加个,条件肯定为false,不进入条件,但会进行预解释var a,此时a 的值为undefined

接下来将他们综合起来先来个简单的综合:

 

1 var name='haha';
2 var age=500;
3 name=(function(name,age){
4     arguments[0]='xixi';
5     age=age||this.age;
6     console.log(name,age);
7 })(name);
8 console.log(name,age)

 

 

 

解析:看到此题,来吧先进行预解释,1.var name;var age;此时有个注意点,name=...;等号后面的函数不会进行预解释。2.代码从上到下执行,name='haha';age=500;3.接下来是个关键点name等于一个自执行函数,先看看它有没有返回值,一个函数执行后若没有返回值则结果都等于undefined,所以此时全局name=undefined,此时自执行函数执行时,函数经过传参,就相当于提前var,所以有私有变量,arguments[0]='xixi';此时就相当于将函数私有作用域中name=xixi;age=age||this.age,自执行函数的this指向为window,"||"为或的意思,有一项成立就行,那么age=500.第一次console结果应该为xixi,500  4.全局的console我们刚才分析了name富裕没有返回值的自执行函数时为undefined,所以结果为undefined,500;



今天先更新点简单的,明天加上内存释放等问题,通过特殊的小技巧让你事半功倍,做爽预解释,不用画图也能看出答案。。。

未完,待续....