1. 理解ECMAScript和JavaScript的关系
ECMAScript是JavaScript的标准,JavaScript是ECMAScript具体实现.
JavaScript包含3部分:
ECMAScript,由ECMA-262定义,提供核心语言功能;- 文档对象模型
DOM,提供访问和操作网页内容的方法和接口; - 浏览器对象模型
BOM,提供与浏览器交互的方法和接口;
有兴趣的可以看看阮一峰老师的《JavaScript语言的历史》.
2. 熟练运用es5、es6提供的语法规范
ES5:
说起es6大家都很熟悉了,但是es5呢?
其实现在我们用的一些语法特性,有些都是es5的,到底有哪些呢?下面我会列举一些:
-
严格模式(
use strict)关于严格模式的使用以及特点,就不多赘述了
-
JSON对象JSON.stringify()、JSON.parse() -
Object扩展Object.create(prototype, [descriptors])、Object.defineProperties(object, descriptors) -
Array扩展Array.prototype.indexOf(value): 得到值在数组中的第一个下标Array.prototype.lastIndexOf(value): 得到值在数组中的最后一个下标Array.prototype.forEach(function(item, index){}): 遍历数组Array.prototype.map(function(item, index){}): 遍历数组返回一个新的数组,返回加工之后的值Array.prototype.filter(function(item, index){}): 遍历过滤出一个新的子数组, 返回条件为true的值
-
Function扩展Function.prototype.bind(obj)
ES6:
推荐阮一峰老师的《ECMAScript6入门》
3. 熟练掌握JavaScript提供的全局对象(例如Date、Math)、全局函数(例如decodeURI、isNaN)、全局属性(例如Infinity、undefined)
全局的对象( global objects )或称标准内置对象,不要和"全局对象(global object)"混淆。这里说的全局的对象是说在全局作用域里的对象。“全局对象 (global object)”可以在全局作用域里,通过this访问(但只有在 ECMAScript 5 的非严格模式下才可以,在严格模式下得到的是undefined)。实际上,全局作用域包含了全局对象的属性,还有它可能继承来的属性。
Date:
创建一个 JavaScript Date实例,该实例呈现时间中的某个时刻。Date对象则基于Unix Time Stamp,即自1970年1月1日(UTC)起经过的毫秒数。
- 如果没有输入任何参数,则
Date的构造器会依据系统设置的当前时间来创建一个Date对象。 - 如果提供了至少两个参数,其余的参数均会默认设置为 1(如果没有指定 day 参数)或者 0(如果没有指定 day 以外的参数)。
JavaScript的时间由世界标准时间(UTC)1970年1月1日开始,用毫秒计时,一天由 86,400,000 毫秒组成。Date对象的范围是 -100,000,000 天至 100,000,000 天(等效的毫秒值)。Date对象为跨平台提供了统一的行为。时间属性可以在不同的系统中表示相同的时刻,而如果使用了本地时间对象,则反映当地的时间。Date对象支持多个处理 UTC 时间的方法,也相应地提供了应对当地时间的方法。UTC,也就是我们所说的格林威治时间,指的是time中的世界时间标准。而当地时间则是指执行JavaScript的客户端电脑所设置的时间。- 以一个函数的形式来调用
Date对象(即不使用new操作符)会返回一个代表当前日期和时间的字符串。
Math:
Math是一个内置对象, 它具有数学常数和函数的属性和方法。不是一个函数对象。
Math 适用于Number类型。它不支持BigInt。
与其他全局对象不同的是,Math不是一个构造器。Math的所有属性与方法都是静态的。引用圆周率的写法是Math.PI,调用正余弦函数的写法是Math.sin(x),x是要传入的参数。Math的常量是使用 JavaScript 中的全精度浮点数来浮点数来定义的。定义的。
decodeURI:
decodeURI()函数解码一个由encodeURI先前创建的统一资源标识符(URI)或类似的例程。
将已编码 URI 中所有能识别的转义序列转换成原字符,但不能解码那些不会被encodeURI编码的内容(例如 "#")。
isNaN:
isNaN()函数用来确定一个值是否为NaN。注:isNaN函数内包含一些非常有趣的规则;你也可以使用 ECMAScript 2015中定义的Number.isNaN()来判断。
isNaN函数的必要性
与 JavaScript 中其他的值不同,NaN不能通过相等操作符(== 和 ===)来判断 ,因为NaN == NaN和NaN === NaN都会返回false。 因此,isNaN就很有必要了。
NaN值的产生
当算术运算返回一个未定义的或无法表示的值时,NaN就产生了。但是,NaN并不一定用于表示某些值超出表示范围的情况。将某些不能强制转换为数值的非数值转换为数值的时候,也会得到NaN。
例如,0 除以0会返回NaN—— 但是其他数除以0则不会返回NaN。
- 令人费解的怪异行为
如果isNaN函数的参数不是Number类型,isNaN函数会首先尝试将这个参数转换为数值,然后才会对转换后的结果是否是NaN进行判断。因此,对于能被强制转换为有效的非NaN数值来说(空字符串和布尔值分别会被强制转换为数值0和1),返回false值也许会让人感觉莫名其妙。比如说,空字符串就明显“不是数值(not a number)”。
这种怪异行为起源于:"不是数值(not a number)"在基于IEEE-754数值的浮点计算体制中代表了一种特定的含义。isNaN函数其实等同于回答了这样一个问题:被测试的值在被强制转换成数值时会不会返回IEEE-754中所谓的“不是数值(not a number)”。
下一个版本的ECMAScript (ES2015)包含Number.isNaN()函数。通过Number.isNaN(x)来检测变量x是否是一个NaN将会是一种可靠的做法。然而,在缺少Number.isNaN函数的情况下, 通过表达式(x != x)来检测变量x是否是NaN会更加可靠。
一个isNaN的 polyfill 可以理解为(这个polyfill利用了NaN自身永不相等于自身这一特征 ):
var isNaN = function(value) {
var n = Number(value);
return n !== n;
};
isNaN(NaN); // true
isNaN(undefined); // true
isNaN({}); // true
isNaN(true); // false
isNaN(null); // false
isNaN(37); // false
// strings
isNaN("37"); // false: 可以被转换成数值37
isNaN("37.37"); // false: 可以被转换成数值37.37
isNaN("37,5"); // true
isNaN('123ABC'); // true: parseInt("123ABC")的结果是 123, 但是Number("123ABC")结果是 NaN
isNaN(""); // false: 空字符串被转换成0
isNaN(" "); // false: 包含空格的字符串被转换成0
// dates
isNaN(new Date()); // false
isNaN(new Date().toString()); // true
isNaN("blabla") // true: "blabla"不能转换成数值
// 转换成数值失败, 返回NaN
Infinity:
全局属性Infinity是一个数值,表示无穷大。
Infinity的属性特性 |
值 |
|---|---|
| writable | false |
| enumerable | false |
| configurable | false |
Infinity是全局对象(global object)的一个属性,即它是一个全局变量。
Infinity的初始值是Number.POSITIVE_INFINITY。
Infinity(正无穷大)大于任何值。该值和数学意义上的无穷大很像,例如任何正值乘以Infinity为Infinity, 任何数值(除了Infinity 和 -Infinity)除以Infinity为 0。
在 ECMAScript 5 的规范中,Infinity是只读的(实现于 JavaScript 1.8.5 / Firefox 4)。
console.log(Infinity ); /* Infinity */
console.log(Infinity + 1 ); /* Infinity */
console.log(Math.pow(10, 1000)); /* Infinity */
console.log(Math.log(0) ); /* -Infinity */
console.log(1 / Infinity ); /* 0 */
undefined:
全局属性undefined表示原始值undefined。它是一个JavaScript的原始数据类型。
undefine的属性特性 |
值 |
|---|---|
| writable | false |
| enumerable | false |
| configurable | false |
undefined是全局对象的一个属性。也就是说,它是全局作用域的一个变量。
undefined的最初值就是原始数据类型undefined。
在现代浏览器(JavaScript 1.8.5/Firefox 4+),自ECMAscript5标准以来undefined是一个不能被配置(non-configurable),不能被重写(non-writable)的属性。
即便事实并非如此,也要避免去重写它。
一个没有被赋值的变量的类型是undefined。如果方法或者是语句中操作的变量没有被赋值,则会返回undefined(对于这句话持疑惑态度,请查看英文原文来理解)。
function test(a){
console.log(typeof a); // undefined
return a;
}
test(); // 返回"undefined"
有兴趣的同学可以看看MDN上的JavaScript 标准内置对象
4. 熟练应用map、reduce、filter 等高阶函数解决问题
5. setInterval需要注意的点,使用setTimeout实现setInterval
- 不能传递带参数的函数
setInterval(function(args){}, 600);
- 如果需要传递参数,可以使用闭包返回一个函数,或者
var intervalID = window.setInterval(myCallback, 500, 'Parameter 1', 'Parameter 2');
function myCallback(a, b)
{
// Your code here
// Parameters are purely optional.
console.log(a);
console.log(b);
}
- 需要使用
clearInterval清除定时器,防止定时器一直执行下去,同时也需要手动释放内存
Var timer = null
If (timer) {
clealInterval(timer)
Timer = null
}
timer = setInterval(callback, 500);
this指向问题
由setInterval()调用的代码运行在与所在函数完全分离的执行环境上。这会导致,这些代码中包含的this关键字在非严格模式会指向window(或全局)对象,严格模式下为 undefined,这和所期望的this的值是不一样的。
使用setTimeout实现setInterval,大体思路就是使用递归不断地执行setTimeout
function mySetInterval(fn, millisec){
function interval(){
setTimeout(interval, millisec);
fn();
}
setTimeout(interval, millisec)
}
6. JavaScript提供的正则表达式API、可以使用正则表达式(邮箱校验、URL解析、去重等)解决常见问题
5个常用方法:
- test
reg.test(str); // 返回是否包含正则 true/false
var str = "abcdefghijkl3mnop2qts";
/\d/.test(str); // true
- match
str.match(reg); // 一般正则表达式加g,会返回包含所有匹配项的数组
var str = "abcdefghijkl3mnop2qts";
str.match(/\d/g); // ["3", "2"]
- search
str.search(reg); // 返回第一条匹配的索引位置
var str = "abcdefghijkl3mnop2qts";
str.search(/\d/); // 12
- replace
str.replace(str/reg, replacement); // 不改变原字符串,返回新字符串
- exec
在循环中反复地调用 exec() 方法是唯一一种获得全局模式的完整模式匹配信息的方法。
7. JavaScript异常处理的方式,统一的异常处理方案
try...catch...finally语句:try语句包含了由一个或者多个语句组成的try块,和至少一个catch子句或者一个finally子句的其中一个,或者两个兼有,下面是三种形式的try声明:
try...catchtry...finallytry...catch...finally
throw语句:
用来抛出一个用户自定义的异常。当前函数的执行将被停止(throw之后的语句将不会执行),并且控制将被传递到调用堆栈中的第一个catch块。如果调用者函数中没有catch块,程序将会终止。
function getRectArea(width, height) {
if (isNaN(width) || isNaN(height)) {
throw "Parameter is not a number!";
}
}
try {
getRectArea(3, 'A');
}
catch(e) {
console.error(e);
// expected output: "Parameter is not a number!"
}
window.onerror
感兴趣的同学可以点这里.