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


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


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

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


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


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


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

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

(function f(){
    function f(){ return 1; }
    alert (f());
    function f(){ return 2; }
})();
解析:此函数为自执行函数,观察函数,注意类似于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()进行函数的调用,alert(a).当前作用域下没
有a,就去父级作用域,a=12; 4.接着执行a=15,任何在函数私有作用域下‘变量‘前面不带var的本身不属于当前作用域域,而是对全局作用域中全局变量的重新赋值,所
以此时相当于把全局变量中的a直接赋值为15; 5.最后在全局作用域下alert(a),只能访问自己的变量。所以a=15;

此题答案为 12,15;

此题引申:


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

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


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

再引申:


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

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


var a=12;
function show(a){
    alert(a);
    a=15;
}
show(a);
alert(a);
此题结果应该为:12,15,此题主要关键点为全局变量的从新赋值:

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


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


此题结果为undefined,12,15,12

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


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


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


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

引申:


if(!"a" in window){
    var a=15;
}
function fn() {
    alert(a)
}
fn()
解析:加个“!”,条件肯定为false,不进入条件,但会进行预解释var a,此时a 的值为undefined,

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


var name=‘haha‘;
var age=500;
name=(function(name,age){
    arguments[0]=‘xixi‘;
    age=age||this.age;
    console.log(name,age);
})(name);
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;

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

未完,待续....


 
时间: 2024-10-06 06:06:20

做预解释题的一点小方法和小技巧的相关文章

预解释继续。。。。。

接着上篇文章我们继续探讨关于预解释的问题:当预解释的函数问题遇见诸如内存释放结合的时候,我们需要格外小心,我们都知道JavaScript属于弱类型语言,起初只是作为浏览器的脚本语言,现今js的用途变得越来越广泛,但作为一种单线程语言,性能优化则变得尤为重要,什么异步回调,浏览器自身的垃圾回收机制等各种行为都是为了优化性能.扯远了,闲话少说,接下来步入正题.为了更好,更快的地运行代码,我们需要了解内存释放机制: - 内存包含:堆内存和栈内存- 堆内存:用来存放数据的:    + 对象数据类型的  

FFT/NTT做题方法与调试技巧(+提高码题效率的一些想法)

(其实本文应该写成了"结合FFT讨论的调试技巧+码题方法",语文不好一写文章就偏题QAQ) 有意见欢迎提出,有遗漏欢迎补充! FFT(快速傅里叶变换)/NTT(数论变换)是卷积运算常见而实用的优化 但是FFT/NTT的处理过程并不像暴力运算(差不多是多项式乘法)那样能够直观地反映卷积结果的实时变化. 因此在使用FFT时将会或多或少地加大调试的难度. 如果调试程序时直接跟踪变量,每步手算结果比对,不仅会耽误大量时间,而且效果可能并不理想. 直接肉眼查错效率可能也不太高. 但也正由于FFT

(转)java中查找List的快捷小方法

相信java开发的程序员,经常会遍历list里的数据,来查找想要的数据.之后选出来在做处理,我这有个小方法在大量数据的情况下能更快捷,当然这方法只对菜鸟有点用,对老鸟来说也许有更好的方法,请指点 遍历list的时候请把list里的每条数据安一个关键字放到map当中去如: for (Map<String, String> subMap : resourceList) {     resourceMap.put(subMap.get("OBJECTNAME"), subMap)

ArrayBlockingQueue take()和poll()等方法的小区别

最近工作中看见一个同事的代码是关于ArrayBlockingQueue方面的使用,然后引出take()和poll()的小小的区别,当然他实现方式是没有错.但是由于选择不当有性能的开销,所以我想这里整理一下关于ArrayBlockingQueue 的理解,纯技术交流.有不正确的地方请谅解.下面对源码做一个导读.首先 ArrayBlockingQueue是一个基于数组.先进先出.线程安全的集合类,其特点是实现指定时间的阻塞读写,并且容量有界的. 1) 构造函数 public ArrayBlockin

吃透【预解释】,从此再也不用担心!

Author:李金涛 Form:光环国际 Time:2017-12-31 23:49(跨年夜的最后一刻,我在辛勤耕耘我的"预解释",收获满满,甚喜!) 定义:预解释(变量提升):js在运行前,先把所有带var和function关键字的提前声明或定义.且预解释是发生当前作用域下的. 1,全局预解释阶段: (1)全局作用域与全局变量:当浏览器加载HTML页面的时候,首先会提供一个供全局JavaScript代码执行的环境,称之为全局作用域(global/ window).在window全局作

HDU 2147--HDU 2147(博弈)--我可能做了假题。。。

kiki's game Time Limit: 5000/1000 MS (Java/Others) Memory Limit: 40000/1000 K (Java/Others) Total Submission(s): 238 Accepted Submission(s): 41 Problem Description Recently kiki has nothing to do. While she is bored, an idea appears in his mind, she

课程笔记:——javascript中的预解释2

in:检测某一个属性是否属于这个对象(既可以检测私有的属性,也可以检测公有的属性) --> attr in obj 1.不管条件是否成立,在预解释的时候,判断体中的带var和function的都要进行预解释window下的预解释: var a; -->a=undefined 我们在全局作用域下声明的变量不仅仅是全局变量,也相当于给window增加了一个叫做"a"的属性名 if (!("a" in window)) {//"a" in

提高自信的30个小方法

你自信吗?面对挫折.压力.困惑.障碍时,我们难免会丧失气场,怀疑自己的能力,但没有真正的自信生活就没有底气和光亮.下面是提高自信的30个小方法,说不定对你有帮助哦~ 1.学习是件好事,所以报个学习班充实一下自己并且享受这种主动学习知识的乐趣.你会发现你的头脑越充实,你就越自信!如果你没有时间上夜校,那么每天晚上给自己留半个小时去阅读吧.我会选择阅读那些我从来没有接触到的领域.比如我是个学习理科的,我就会让自己读些管理学,经济学,政治,宗教的书籍.虽然有的时候我并不能理解书中的内容,但就是抱着一种

JS 预解释相关理解

1.JS中的内存空间分为两种:栈内存.堆内存 栈内存:提供JS代码执行的环境;存储基本数据类型的值; ->全局作用域或者私有的作用域其实都是栈内存 堆内存:存储引用数据类型的值(对象是把属性名和属性值存储进去,函数是把函数体中的代码当做字符串存储进去) 2.当浏览器加载我们HTML页面的时候,首先会提供一个供JS代码执行的环境->全局作用域(global->window) 3.在JS代码执行之前,浏览器还需要自己做一些事情:把所有带var/function关键字的进行提前的声明或者定义