接触JavaScript两年多遇到过各种错误,其中有一些让人防不胜防,原来对JavaScript的误会如此之深,仅以此文总结一下常见的各种想当然的误区。
String replace
string的replace方法我们经常用,替换string中的某些字符,语法像这样子
1
|
string.replace(subStr/reg,replaceStr/ function )
|
第一个参数是要查找的字符串或者一个正则表达式,第二个参数是想替换成的字符串或一个方法,我们可以这么使用
1
|
"I'm Byron" .replace( "B" , "b" ) // I'm byron
|
记过和我们想得一样,但是
1
|
"I'm a student, and you?" .replace( "n" , "N" ); // I'm a studeNt, and you?
|
和我们预期的不一样,第二个‘n’没有被替换。字符串的 replace 方法如果第一个参数传入字符串,那么只有第一个匹配项会被替换。如果要替换全部匹配项,需要传入一个 RegExp 对象并指定其 global 属性。
1
|
"I'm a student, and you?" .replace(/n/g, "N" ); // I'm a studeNt, aNd you?
|
这样才可以达到我们目的
Date 对象
我们可以这样构造一个Date对象
1
2
3
4
|
new Date() //Date {Fri Aug 02 2013 16:50:33 GMT+0800 (China Standard Time)}
new Date(milliseconds) //Date {Fri Aug 02 2013 16:53:26 GMT+0800 (China Standard Time)}
new Date( "2013/08/02" ) //Date {Fri Aug 02 2013 00:00:00 GMT+0800 (China Standard Time)}
new Date(year,month,day,hours,minutes,seconds,ms)
|
前三种方式没有什么问题,但第四种得到的结果回合我们预期的不一致
1
|
new Date(2013,08,02) //Date {Mon Sep 02 2013 00:00:00 GMT+0800 (China Standard Time)}
|
我们可以看到,传入的月份是08,返回的结果却是九月。这是因为Date对象的月份是从0开始计数的(天却不是),即0代表一月,1代表二月…11代表12月。在调用Date实例的getMonth方法时尤其要注意
1
2
|
var d = new Date(2012, 4, 15); // 2012年5月15日
alert(d.getMonth()); // 结果为4
|
Date.parse
Date.parse方法可以识别两种格式的字符串参数(标准的长日期格式,比如带星期的那种,也可以识别,不过不常用):
1. “M/d/yyyy”: 美国的日期显示格式。如果年传入2位则作为 19xx 处理
2.”yyyy-MM-dd” 或 “yyyy/MM/dd”: 注意月和日都必须是两位
Date.parse 的返回结果不是一个Date对象,而是从1970-01-01午夜(GMT)到给定日期之间的毫秒数。可以用Date的构造函数将其转换为Date对象。
1
2
3
|
new Date(Date.parse( "8/2/2012" )); // 正确识别为2012年8月2日
new Date(Date.parse( "2012-08-02" )); // 正确识别为2012年8月2日
new Date(Date.parse( "2012-8-2" )); // 不能识别
|
for…in 遍历数组
for…in用来遍历一个对象中的成员(属性,方法),如果用来遍历数组的到的结果并不是预期中数组每项的值,方法神马的会被遍历出来
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
Array.prototype.contains = function (item) {
for ( var i = 0; i <= this .length - 1; i++) {
if ( this [i] == item)
return this [i];
} } var staff = [ "Staff A" , "Staff B" ];
// Normal Enumeration: Only the 2 items are enumerated for ( var i = 0; i <= staff.length - 1; i++) {
var singleStaff = staff[i];
alert(singleStaff); } // for...in Enumeration: the method "contains" are enumerated, too for ( var singleStaff in staff) {
alert(singleStaff); } |
事实上很多时候我们都会给数组加上其他属性。比如 jQuery 对象就是一个数组对象加上一些扩展方法;再比如 String.prototype.match 方法返回值就是一个数组(正则表达式及其子表达式的匹配项)加上 index 和 input 两个属性。
parseInt
语法: parseInt(string, radix)
参数 | 描述 |
string | 必需。要被解析的字符串。 |
radix | 可选。表示要解析的数字的基数。该值介于 2 ~ 36 之间。如果省略该参数或其值为 0,则数字将以 10 为基础来解析。如果它以 “0x” 或 “0X” 开头,将以 16 为基数。如果该参数小于 2 或者大于 36,则 parseInt() 将返回 NaN。 |
当参数 radix 的值为 0,或没有设置该参数时,parseInt() 会根据 string 来判断数字的基数。
举例,如果 string(开头结尾空格自动省略) 以 “0x” 开头,parseInt() 会把 string 的其余部分解析为十六进制的整数。如果 string 以 0 开头,那么 ECMAScript v3 允许 parseInt() 的一个实现把其后的字符解析为八进制或十六进制的数字。如果 string 以 1 ~ 9 的数字开头,parseInt() 将把它解析为十进制的整数。如果字符串的第一个字符不能被转换为数字,那么 parseFloat() 会返回 NaN。
1
2
3
4
5
6
|
parseInt( "10" ); //返回 10
parseInt( "19" ,10); //返回 19 (10+9)
parseInt( "11" ,2); //返回 3 (2+1)
parseInt( "17" ,8); //返回 15 (8+7)
parseInt( "1f" ,16); //返回 31 (16+15)
parseInt( "010" ); //未定:返回 10 或 8
|
setTimeout/setInterval执行时机
setTimeout()和setInterval()经常被用来处理延时和定时任务。setTimeout() 方法用于在指定的毫秒数后调用函数或计算表达式,而setInterval()则可以在每隔指定的毫秒数循环调用函数或表达式,直到clearInterval把它清除。
JavaScript其实是运行在单线程的环境中的,这就意味着定时器仅仅是计划代码在未来的某个时间执行,而具体执行时机是不能保证的,因为页面的生命周期中,不同时间可能有其他代码在控制JavaScript进程。在页面下载完成后代码的运行、事件处理程序、Ajax回调函数都是使用同样的线程,实际上浏览器负责进行排序,指派某段程序在某个时间点运行的优先级。
我们可以可以把JavaScript想象成在时间线上运行。当页面载入的时候首先执行的是页面生命周期后面要用的方法和变量声明和数据处理,在这之后JavaScript进程将等待更多代码执行。当进程空闲的时候,下一段代码会被触发
除了主JavaScript进程外,还需要一个在进程下一次空闲时执行的代码队列。随着页面生命周期推移,代码会按照执行顺序添加入队列,例如当按 钮被按下的时候他的事件处理程序会被添加到队列中,并在下一个可能时间内执行。在接到某个Ajax响应时,回调函数的代码会被添加到队列。JavaScript中没有任何代码是立即执行的,但一旦进程空闲则尽快执行。定时器对队列的工作方式是当特定时间过去后将代码插入,这并不意味着它会马上执行,只能表示它尽快执行。
预解析
1
2
3
4
|
console.log(a); //Error:a is not defined ,直接报错,下面语句没法执行,一下结果为注释该句后结果
console.log(b) //undefined
var b= "Test" ;
console.log(b); //Test
|
很奇怪前两句变量a,b都没有声明,第一句却报错,第二句能够输出undefined?这是因为JavaScript 是解释型语言,但它并不是直接逐步执行的,JavaScript解析过程分为先后两个阶段,一个是预处理阶段,另外一个就是执行阶段。在预处理阶段 JavaScript解释器将完成把JavaScript脚本代码转换到字节码,然后第二阶段JavaScript解释器借助执行环境把字节码生成机械 码,并顺序执行。
也就说JavaScript值执行第一句语句之前就已经将函数/变量声明预处理了,var b=”Test” 相当于两个语句,var b;(undefined结果的来源,在执行第一句语句之前已经解析),b=”Test”(这句是顺序执行的,在第二句之后执行)。这也是为什么我们可以 在方法声明语句之前就调用方法的原因。
1
2
3
4
5
|
showMsg(); // This is message
function showMsg()
{ alert( 'This is message' );
} |
块级作用域
JavaScript没有块级作用域,只有函数级作用域,这就意味着{}在JavaScript中只能起到语法块的作用,而不能起到作用域块作用
1
2
3
4
5
|
if ( true ){ //语法块,保证{}内代码if条件成立执行
//...
var a=3;
} console.log(a); //3
|
上面例子可以清楚看到属于window的console.log方法依然可以访问貌似是局部变量的a
闭包
首先从一个经典错误谈起,页面上有若干个div, 我们想给它们绑定一个onclick方法,于是有了下面的代码
1
2
3
4
5
6
|
<div id= "divTest" >
<span>0</span> <span>1</span> <span>2</span> <span>3</span>
</div>
<div id= "divTest2" >
<span>0</span> <span>1</span> <span>2</span> <span>3</span>
</div>
|
1
2
3
4
5
6
7
8
|
$(document).ready( function () {
var spans = $( "#divTest span" );
for ( var i = 0; i < spans.length; i++) {
spans[i].onclick = function () {
alert(i);
}
}
});
|
很简单的功能可是却偏偏出错了,每次alert出的值都是4,简单的修改就好使了
1
2
3
4
5
6
7
8
9
10
|
var spans2 = $( "#divTest2 span" );
$(document).ready( function () {
for ( var i = 0; i < spans2.length; i++) {
( function (num) {
spans2[i].onclick = function () {
alert(num);
}
})(i);
}
});
|
闭包是指有权限访问另一个函数作用域的变量的函数,创建闭包的常见方式就是在一个函数内部创建另一个函数,只要存在调用内部函数的可 能,JavaScript就需要保留被引用的函数。而且JavaScript运行时需要跟踪引用这个内部函数的所有变量,直到最后一个变量废 弃,JavaScript的垃圾收集器才能释放相应的内存空间。
相关推荐
通过避免这些常见误区,并采取上述解决方案,可以有效地改善CSS和HTML的使用效率,提升开发和维护的便捷性。同时,这也是前端开发的最佳实践,有助于提升网站的整体性能和用户体验。希望这些内容能够帮助大家更好地...
该文档不仅帮助开发者规避常见的误区与微妙的bug,还提供了性能优化建议以及避免不良实践的方法。对于希望深入了解JavaScript特性的非专家级程序员来说,《JavaScript Garden》是一份宝贵的资源。 #### 关于...
这本书可以帮助开发者提升编写高效、可维护代码的能力,并了解如何避免常见的陷阱和误区。 至于“新建文件夹”,这可能是一个存放这些PDF文档的目录。在实际使用中,将相关的学习资料组织在同一个文件夹下,有助于...
《JavaScript语言精粹_修订版》这本书不仅涵盖了以上知识点,还可能详细讲解了各种最佳实践、陷阱和常见误区,旨在帮助开发者写出更高质量的JavaScript代码。通过深入学习和实践,你可以成为一名精通JavaScript的...
同时,作者还提醒读者注意JavaScript的潜在陷阱和常见误区,避免在实际开发中遇到问题。 总的来说,《JavaScript权威指南》是一本深入且全面的JavaScript参考书,无论你是初学者还是经验丰富的开发者,都能从中...
### JavaScript学习文档精要 #### 一、脚本语言概览 在深入探讨JavaScript之前,有必要先理解脚本语言的基本...同时,了解JavaScript与Java之间的区别,有助于避免常见的认知误区,为后续的学习和发展奠定坚实基础。
### JavaScript面试题知识点详解 #### 一、单选题知识点 ...以上是对题目中知识点的详细解释,这些知识点涵盖了JavaScript的基础概念、语言特性以及一些高级用法,对于面试准备来说是非常重要的内容。
常见错误二:传统编程语言的生命周期误区 常见错误三:内在泄露 常见错误四:比较运算符 常见错误五:低效的DOM操作 常见错误六:在for循环中的不正确函数调用 常见错误七:原形继承问题 常见错误八:为实例方法创建...
3. **JavaScript理解误区**: - A选项:JScript是Microsoft对JavaScript的实现,不是其简称。 - B选项:JavaScript并非Java的简化版本,而是完全独立的语言。 - C选项:Firefox和IE的兼容性问题主要源于它们对...
然而,关于原型链和原型,有一个常见的误区。 首先,我们需要弄清楚原型链的概念。在JavaScript中,每个对象都有一个内部链接指向另一个对象,即它的原型对象。当试图访问一个对象的属性时,如果在当前对象上没有...
在JavaScript编程中,初学者经常会遇到一些陷阱,这些陷阱可能会导致程序行为不符合预期。以下是对这些常见陷阱的详细解释和解决方法: 1. **数组排序陷阱**:当你使用`Array.prototype.sort()`方法对数字数组进行...
然而,在使用`prototype`为对象添加属性时,存在一些常见的误区,可能导致程序行为不符合预期。以下是一些关于`prototype`添加属性的详细解释和注意事项: 1. **属性访问效率**:在JavaScript中,通过`prototype`...
然而,在使用JavaScript的过程中,开发者们常常会遇到一些错误。下面将详细介绍在JavaScript中常见的十种错误,并提供解决方法和相关知识点。 1. this关键字的错误使用: 在JavaScript中,this关键字代表函数执行时...
JavaScript,作为世界上最受欢迎的编程语言之一,经常会给开发者带来一些陷阱和误区,这些陷阱可能导致程序出乎意料的行为。在“js-pitfall-examples”这个项目中,我们收集了一些常见的JavaScript陷阱,通过实例来...
在实践这些技术时,可能会遇到一些常见误区,例如: 1. 忘记设置`z-index`,导致下拉列表被其他元素覆盖。 2. 对于图片替换,不设置`text-indent`或`overflow`,导致文字内容仍然可见。 3. 在模拟下拉条时,没有...
【前端面试题(JavaScript)】 前端面试中,JavaScript 相关的问题是不可或缺的一部分。...以上是对前端面试中常见 JavaScript 知识点的详细解析,这些知识点不仅在面试中常见,也是开发中不可或缺的基础技能。
通过大量的实例分析和实战练习,课程将帮助您避免常见的JavaScript编程误区,提高代码质量。无论是为了个人兴趣还是职业发展,这门课程都将极大地提升您对JavaScript的理解和应用能力,为成为Web全栈开发者奠定坚实...