javascript代码编写中的各种坑和坑
坑中的单词是陷阱,由于javascript语言的脆弱性,使得它在使用过程中容易灵活,但也很容易招到,这些坑往往是隐藏的,所以你要擦亮眼睛,这样才能在学习和应用JS的过程中走得很顺利。1。全局变量
Javascript通过函数管理函数的范围,函数中声明的变量只在函数中,函数的外部是不可用的,另一方面,全局变量是直接声明或未声明的,简单地在任何函数之外使用。
未声明的直接和简单的使用是指使用var关键字来声明变量。这对我们来说非常清楚,避免隐式生成全局变量的方法是声明变量尽可能地用作var键。
但是你觉得VaR可以吗看那个坑:
复制代码代码如下所示:
函数(){
var a = b = 0;
/主体…
}
也许您所期望的是两个局部变量,但B是一个真正的全局变量:
复制代码代码如下所示:
函数(){
var =(b = 0);
/主体…
}
所以B是一个全局变量。
填坑:声明一个变量,最好的一个,不搞批发~ _ ~;
两。变量声明
先看坑:
复制代码代码如下所示:
我的名字是全球;
函数(){
警报(名字);
var myName =地方;
警报(名字);
}
(富);
乍一看,我们期望两个警报时间的结果分别是全局和局部的,但真正的结果是未定义的和本地的。为什么因为变量位于同一个函数域(相同的函数),而声明首先解析到作用域的顶部。
因此,上述代码片段的执行可能如下所示:
复制代码代码如下所示:
函数(){
VaR的名字;
警报(名字); / / 的定义
我的名字是地方;
警报(名字); / / 的地方
}
用另一个坑,如果你真的了解preresolution测试:
复制代码代码如下所示:
如果(!(窗口中的){
var a=1;
}
警报(a);
该变量声明是先进的代码顶部,此时不分。接下来,我们进入if语句判断,窗口已经建立(一个被声明为全局变量)的条件,所以判断的陈述是错误的结果,这是直接的if语句,所以A的值是未定义的。
复制代码代码如下所示:
var
console.log(窗口 / /真实);
如果(!(窗口中的){
var a = 1; / 实现
}
警报(a);未定义
凹坑:变量声明,最好是手动放置在作用域的顶部,用于当前不能分配的变量,并且可以先声明然后分配。
三。函数声明
在解析和评估任何表达式和语句之前,函数声明也被推进到作用域的顶部。
复制代码代码如下所示:
警报(类Foo); / / 功能
函数(){
/主体…
}
可以比较。
复制代码代码如下所示:
警报(类Foo); / / 的定义
函数(){()
/主体…
};
如果你知道真相,你会踩到下面的坑吗
复制代码代码如下所示:
函数测试(){
警报(1);
}
测试();
函数测试(){
警报(2);
}
测试();
运行上面的代码片段,你看到的是2个弹出窗口。为什么不是1和2,分别很简单,测试的声明之前解析试验(),因为后者overovers前者,所以两执行结果为2。
凹坑:在大多数情况下,我使用函数表达式替换函数声明,尤其是在某些语句块中。
四,函数表达式
首先看看名称函数表达式,当然,它必须有一个名称,例如:
复制代码代码如下:var函数=
/主体…
};
需要注意的是,函数名只对其函数的内部函数可见:
复制代码代码如下所示:
var(=){
(富);正常操作
};
(食品); / /错误:referenceerror
坑:尽量不要使用命名函数表达式(除了一些递归和使用调试),不要使用外部的函数名。
五。函数的自执行
对于函数表达式,可以通过从()后面添加()来执行,并且参数可以在括号中传递,函数声明不能是:
复制代码代码如下所示:
(1)这是一个分组运算符,而不是函数调用!
因此,这里没有实现函数,仍然是一个语句。
函数(x){
警报(x);
}(1);
下面的代码片段分别由1执行,因为它们都是(1)之前的所有函数表达式,所以这里的非组运算符用于表示调用。
将代码复制如下:匿名函数表达式标准
var函数=(x){
警报(x);
}(1);
前面(函数)将被转换为表达式语句。
(函数富(x){)
警报(x);
})(1);
在()中的表达式
(函数富(x){)
警报(x);
}(1);
新表达式
新的函数富(x){
警报(x);
}(1);
| | / /,,,+,-,~!运算符(和逗号),消除函数表达式和函数语句中的歧义。
因此,一旦解析器知道了一个表达式,所有其他默认表达式
真函数富(x){
警报(x);
}(1);
填补坑:坑的关键是找出形式的表达的本质。
六。循环闭合闭包
下面是一个普通的坑:
复制代码代码如下所示:
文件
单击下面的链接时,显示其序列号。
链接# 0
链接# 1
链接# 2
链接# 3
链接# 4
复制代码代码如下所示:
VaR的链接= document.getelementsbytagname(UL){ 0 }。getElementsByTagName();
对于(var i = 0,L = links.length;i < L;i++){
链接{我}。onclick=功能(e){
E.preventDefault();
警报(你点击链接# +我);
}
}
我们期望当我们点击第一个i链接时,我们得到这个序列的索引i的值。事实上,不管我们点击哪个链接,我们都会得到循环后的最终结果:5。
解释为什么:当警报被调用时,for循环中的匿名函数表达式保持对外部变量的引用(闭包)i。当循环结束时,i的值被修改为5。
填充这个坑:为了获得想要的结果,你需要在每个周期中创建变量i的副本:
复制代码代码如下所示:
文件
单击下面的链接时,显示其序列号。
链接# 0
链接# 1
链接# 2
链接# 3
链接# 4
复制代码代码如下所示:
VaR的链接= document.getelementsbytagname(UL){ 0 }。getElementsByTagName(一);
对于(var i = 0,L = links.length;i < L;i++){
链接{我}。onclick=(函数(指数){)
返回函数(e){
E.preventDefault();
警报(你点击链接# +指数);
}
})(一);
}
可以看出(函数(})}的形式是上面提到的自执行函数,而我作为参数传递给index)。当警报再次执行时,它有一个对索引的引用,这个索引在这个时候不会被循环改变。当然,当您理解这个原理时,您也可以编写这个:
复制代码代码如下所示:
对于(var i = 0,L = links.length;i < L;i++){
(函数(索引){)
链接{我}。onclick=功能(e){
E.preventDefault();
警报(你点击链接# +指数);
}
})(一);
}
它也起作用。