根据RedMonk发布的2018年初编程语言排行榜显示,JavaScript高居榜首,说明JavaScript的火热程度,其从90年代初诞生到现在经历了几个大的版本迭代:
- ES3,JavaScript 的第三版,从 1999 年开始
- ES5,2009 年发布
- ES6,2015年6月17日,ECMAScript 6发布正式版本,即ECMAScript 2015
作为开发人员,我们需要拥抱变化,掌握并使用新版本,同时也要了解版本之间的差异,评估历史遗留代码是不是需要改进、甚至重构。本文讨论ES5的新特性及ES3和ES5的区别。
1、保留关键字
Javascript 的保留关键字不可以用作变量、标签或者函数名。有些保留关键字是作为 Javascript 以后扩展使用。ES5较ES3新添加了几个保留关键字:
1)class:类,ES6引入
2)const:常量,ES6引入
3)enum:
4)extends:类继承,ES6引入
5)import:模块导入,ES6引入
6)export:模块导出,ES6引入
7)super:调用父类的构造函数,ES6引入
2、浏览器兼容性
参考:https://caniuse.com/#search=ES5说明
1)ES3,可以认为所有浏览器都支持;
2)ES5,现代浏览器都支持(>=IE9), IE9不支持严格模式。
3、ES5丰富了对象方法、属性处理
1)ES5属性增加getter、setter存储器,看个demo就明白了:
// ES3
var o = (function(){
var age = 0;
return {
get_age:function(){ return age; },
set_age:function(v){ age = v; }
}
})();
console.log(o.get_age()); // 0
o.set_age(12);
console.log(o.get_age()); // 12
// ES5
var o = (function(){
var age = 0;
return {
get age (){return age;},
set age (v){ age = v; }
}
})();
console.log(o.age); // 0
o.age =12;
console.log(o.age); // 12
2)ES5属性增加可读写、可遍历、是否可删除设置,看个案例:
- Configurable:表示能否通过delete删除属性或者删除后从新定义值,或者能把属性修改为访问器属性,默认true。
- Enumerable:表示能否通过for-in遍历属性的值,默认为true。
- Writable:表示能否直接定义属性的值,默认为true。
- Value:表示属性对应的值,默认值为undefined。
var o5={}
Object.defineProperty(o5,"name",{
writable:false, //可赋值?
configurable:false, //可删除?
enumerable:true, //可遍历?
value:"oes5" //当前name属性的具体值
})
console.log(o5.name) //oes5
o5.name="321"
console.log(o5.name) //writable为false, 赋值失效, name依然为"oes5"
delete o5.name
console.log(o5.name) //因为configurable为false所以不能删除, name依然为“oes5”
3)Object增加了很多方法
- Object.defineProperties(obj, propName, descriptorSet) 定义对象属性,上文DEMO已经提及
- Object.create(protoObj, descriptorSet),对象创建函数,一个很关键的函数,可以解决对象继承问题;
- Object.getOwnPropertyNames(obj),获取对象自有属性名称
- Object.getPrototypeOf(obj),获取对象原型对象,=== obj.proto
- Object.getOwnPropertyDescriptor(obj, propName),获取属性定义描述对象{configurable,enumerable,value,writable}
- Object.preventExtensions(obj),阻止对象扩展,对象不能增加新属性
- Object.isExtensible(obj),判断对象是否可扩展
- Object.seal(obj),密封对象,保护对象属性除值外,其余定义属性都不能修改,也不能新增、删除属性;
- Object.isSealed(obj):判断对象是否被密封;
- Object.freeze(obj):对象冻结,对象属性不能修改,包括值;
- Object.isFrozen(obj):判断对象是否被冻结;
- Object.keys(obj):获取对象可枚举的自有属性名称,是getOwnPropertyNames(obj)的子集。
4、ES5的函数特性,新增bind方法
参考MDN web docs,The bind() method creates a new function that, when called, has its this keyword set to the provided value, with a given sequence of arguments preceding any provided when the new function is called.
The bind() 创建了一个新function,this执行bind对象,看个DEMO。
var module = {
x: 42,
getX: function() {
return this.x;
}
}
var unboundGetX = module.getX;
console.log(unboundGetX()); //全局作用域, ->undefiend
var boundGetX = unboundGetX.bind(module); //bind, this->module
console.log(boundGetX()); //this.x = module.x = 42
ES3中,我们可以通过apply或者call实现bind操作。
5、ES5 数组增加很多方法
2个索引方法:indexOf() 和 lastIndexOf();
5个迭代方法:forEach()、map()、filter()、some()、every();
2个归并方法:reduce()、reduceRight(),具体如下:
- Array.prototype.indexOf()
Returns the first (least) index of an element within the array equal to the specified value, or -1 if none is found. - Array.prototype.lastIndexOf
Returns the last (greatest) index of an element within the array equal to the specified value, or -1 if none is found. - Array.prototype.every
Returns true if every element in this array satisfies the provided testing function. - Array.prototype.some
Returns true if at least one element in this array satisfies the provided testing function. - Array.prototype.forEach
Calls a function for each element in the array. - Array.prototype.map
Creates a new array with the results of calling a provided function on every element in this array. - Array.prototype.filter
Creates a new array with all of the elements of this array for which the provided filtering function returns true. - Array.prototype.reduce
Apply a function against an accumulator and each value of the array (from left-to-right) as to reduce it to a single value. - Array.prototype.reduceRight
Apply a function against an accumulator and each value of the array (from right-to-left) as to reduce it to a single value.
看个DEMO。
var dataArray = [1, 7, 5, 6, 1, 7, 3];
console.log(dataArray.indexOf(7)); // 1 缺省从0即第一项开始查找
console.log(dataArray.indexOf('7')); // -1, ===比较,7!=='7'
console.log(dataArray.indexOf(7, 's')); // 1 格式不正确, 从第一项开始查找
console.log(dataArray.indexOf(7, 2)); // 5 从第三个项开始查找
console.log(dataArray.lastIndexOf (7)); // 5 缺省从末尾第一项开始查找
console.log(dataArray.lastIndexOf (7, 's'));// -1 格式不正确, 从第一项开始查找
console.log(dataArray.lastIndexOf (7, 2)); // 1 从末尾第三项往前查找
// 数组每个元素是否>1
var every_rst = dataArray.every(function(ele) {
return ele > 1;
})
console.log("every_rst: ", every_rst);
//数组是否有元素>5
var some_rst = dataArray.some(function(ele) {
return ele > 5;
})
console.log("some_rst: ", some_rst);
var filter_rst = dataArray.filter(function(ele) {
return ele > 5;
})
console.log("filter_rst: ", filter_rst);
var map_rst = dataArray.map(function(ele) {
return ele + 5;
})
console.log("filter_rst: ", map_rst);
var forEach_rst = "";
dataArray.forEach(function(ele, index) {
forEach_rst += (index == 0) ? ele : ',' + ele;
});
console.log("forEach_rst: ", forEach_rst);
var reduce_rst = dataArray.reduce(function(prev, cur) {
return prev + cur
});
console.log("reduce_rst: ", reduce_rst);
// reduceRight,从右向左
6、JSON
ES5提供一个内置的(全局)JSON对象,可用来序列化( JSON.stringfy )和反序列化( parse )对象为JSON格式。
- JSON.stringify(),js对象转换成json字符串
- JSON.parse(),解析json字符串,构建js对象,看个DEMO。
var jsonObj = { x: 5, y: 6 };
var jsonStr = JSON.stringify(jsonObj);
var jsonObj2 = JSON.parse(jsonStr);
console.log(jsonStr); //{"x":5,"y":6}
console.log(jsonObj2, jsonObj == jsonObj2);//Object { x: 5, y: 6 } false
7、Strict Mode
In ES3 or ES5-nonstrict, Failure is silent. Execution will proceed assuming success. And we can’t check after every assignment to see if it succeeded. In ES5, Failed assignments throw. A subset intended to provide more thorough error checking and avoid error-prone constructs.
ES5引入了严格模式,默认不启用,可以通过2种生效方式:
- 全局生效,包括通过src引入的js文件,在js代码第一行 “use strict”;
- 函数生效,函数第一行 “use strict”;
关于Javascript严格模式详细说明,大家可以参考:
1)Javascript 严格模式详解
2)MDN web docs: Strict mode
启用严格模式后,js代码语法和行为将会发生一定改变,具体可以参考上述两篇博文,其中this为undefined时,不再指向global,本文之前的一个DEMO在严格模式下,js会报错。
"use strict";
var module = {
x: 42,
getX: function() {
return this.x;
}
}
var unboundGetX = module.getX;
console.log(unboundGetX()); //全局作用域, ->undefiend
var boundGetX = unboundGetX.bind(module); //bind, this->module
console.log(boundGetX()); //this.x = module.x = 42
运行该段代码,会报 TypeError: this is undefined,原因:
非严格模式下,this为undefined时,会指向global;而严格模式下不会,所以取this.x值就报错了。