题记:作者有个观点,学习ES6之前,必须先懂ES5,恰巧和我的观点吻合,这里找到作者2014年写的讲的ES5的文章,因而翻译了下来。下面的内容捡重点翻译,不重要的略过,文中ES5和ES5.1含义相同。
原文:Thinking About ECMAScript 5 Parts
ES5.1的浏览器支持情况
所有现代浏览器都支持ECMAScript 5.1(ie9+, chrome 19+, safari 5+, firefox 4+, opera 12+, Android 3+, Blackberry Browser 7+, iOS safari 5+, opera mobile 12+, ie Mobile 10+) ,除了IE9不支持严格模式(直到IE10才支持)。
IE8仅支持ES3
IE8仅支持部分ES5.1的特性,比如JSON,Object.defineProperty,Object.getOwnPropertyDescriptor,所以可以认为IE8是仅支持ES3的浏览器。
尾部逗号
ES5规定,对象最后一个属性、数组的最后一个元素后面允许存在逗号。
var myObject = { foo:‘foo‘, bar:‘bar‘, //no error }; var myArray = [1,2,3,]; console.log(myArray.length) //logs 3, regardless of trailing comma
使用反斜杠\构造多行字符串
为构造多行文本字符串,只需要在每行的末尾写上反斜杠\即可。
var stringLiteral = "Lorem ipsum dolor sit amet, consectetur \ elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea";
这并不是最好的方法,但是比起ES3要好很多。
对象属性可以使用保留关键词
下面是示例:
var myObject = {function:‘function‘,new:‘new‘}; console.log(myObject.function,myObject.new); //logs ‘function new‘
JSON对象及其方法
ES5规定了JSON.parse和JSON.stringify方法。
字符串的trim方法
return ‘ foo ‘.trim(); //returns ‘foo‘
字符串可以使用类似数组下标的方式访问字符
return ‘ES5‘[1]; // returns "S"
undefined,NaN,Infinity是只读常量
在es5中,这些是只读常量,无法通过像 undefined="foo bar"的方式被重新定义。
使用Array.isArray判断是否是数组
return Array.isArray([]); //returns true
新的数组方法
es5定义了下面8个数组方法。
Array.prototype.every() Array.prototype.filter() Array.prototype.forEach() Array.prototype.indexOf() Array.prototype.lastIndexOf() Array.prototype.map() Array.prototype.reduce() Array.prototype.some()
这几个方法可以通过函数的call方法,用在其他类数组对象上,可以认为这些方法是“泛型方法”。
//use forEach on string, logging each character in string [].forEach.call(‘ABC‘,console.log); //user forEach on array-like object (i.e. arguments), logging each argument passed var myFunction = function(a,b,c){ [].forEach.call(arguments,console.log); }; myFunction(1,2,3);
上面的forEach,every,some,filter,map的参数类型是函数,他们还接收一个可选的对象类型的参数,作为其函数参数的this对象(即函数的上下文)。
var arrayLikeObject = {0:‘f‘,1:‘o‘,2:‘g‘,length:3}; //call foreach, set the callback this value to arraylikeObject [].forEach.call(arrayLikeObject,function(item){ //inside of function this = arrayLikeObject console.log(item + ‘ total: ‘ + this.length); },arrayLikeObject); //notice third argument, passing arraylikeObject
新的对象访问器属性
在ES3中仅仅存在数据属性,在ES5中新增了访问器属性,在读或者写对象属性的时候,可以调用函数。语法示例如下:
var myObject = { //name:‘‘, WOULD CAUSE ERROR get name() { //notice use of get to indicate accessor property console.log(‘read name‘); }, set name(value) { //notice use of set to indicate accessor property console.log(‘wrote to name the value: ‘ + value); } }; myObject.name = ‘codylindley‘; //invokes set myObject.name; //invokes get
对象属性的可配置特性
ES5新增了对象属性的可配置特性,使得在定义对象属性的时候,可以配置该属性是否可写(Writable)、可枚举(enumerable)、可删除(configurable)。使用Object.getOwnPropertyDescriptor()可以取得属性的特性描述情况。
var accessor = { get name(){}, set name(){} }; var data = {name:‘Cody Lindley‘}; //logs {get: function, set: function, enumerable: true, configurable: true} console.log(Object.getOwnPropertyDescriptor(accessor,‘name‘)); //logs {value: "Cody Lindley", writable: true, enumerable: true, configurable: true} console.log(Object.getOwnPropertyDescriptor(data,‘name‘));
定义对象属性的新方式
ES5新增了Object.defineProperty和Object.defineProperties两个方法,用于定义对象的属性,前者定义单个属性,后者定义多个属性。
var data = {}; //create data object Object.defineProperty( //define properties on data object data, "age", { value: 38, writable: true, enumerable: true, configurable: true } ); var accessor = {}; //create accessor object Object.defineProperty( //define properties on accessor object accessor, "name", { get: function () {}, set: function (value){}, enumerable: true, configurable: true } ); //logs {value: 38, writable: true, enumerable: true, configurable: true} console.log(Object.getOwnPropertyDescriptor(data,‘age‘)); //logs {get: function, set: function, enumerable: true, configurable: true} console.log(Object.getOwnPropertyDescriptor(accessor,‘name‘));
上面示例用Object.defineProperty分别定义了数据属性age和访问器属性name,并定义了该属性的可写、可枚举、可删除特性。
var cody = {}; //create cody object Object.defineProperties( //define age and name properties on cody object cody, { "age": { value: 38, writable: true, enumerable: true, configurable: true }, "name": { get: function(){}, set:function(value){}, enumerable: true, configurable: true } } ); //logs {value: 38, writable: true, enumerable: true, configurable: true} console.log(Object.getOwnPropertyDescriptor(cody,‘age‘)); //logs {get: function, set: function, enumerable: true, configurable: true} console.log(Object.getOwnPropertyDescriptor(cody,‘name‘));
注意使用Object.defineProperty和Object.defineProperties定义的属性,默认是不可写(Writable)、不可枚举(Enumerable),不可删除(Configurable)的。
遍历对象属性
ES5新增了Object.keys和Object.getOwnPropertyNames两个方法,用于遍历对象属性。两个方法的共同点是都不会遍历继承的属性,不同点Object.keys仅仅返回可枚举属性,而Object.getOwnPropertyNames则会返回所有的属性,包括不可枚举的属性。
var person = {}; Object.defineProperties(person, { "name": {value: ‘Cody Lindley‘,enumerable: true}, "age": {value: 38,enumerable: false} } ); //return array of all properties that are enumerable console.log(Object.keys(person)); //logs ["name"] //return array of all properties, including ones that are non-enumerable console.log(Object.getOwnPropertyNames(person)); //returns ["name", "age"]
对象的保护方法
ES5新增了Object.preventExtensions,Object.seal,Object.freeze三个方法,用于保护对象不被改变,级别从低到高。
1)Object.preventExtensions,阻止添加新属性到对象中,但是原有属性可写可删除
2)Object.seal包含Object.preventExtensions的功能,还将所有属性变成不可删除(Non-Configurable)
3)Objec.freeze包含Object.preventExtensions和Object.seal的功能,且讲所有的属性变成不可写(Non-Writable)
除了上面三个方法外,还定义了如下几个方法用于判断对象的状态。
Object.isExtensible() Object.isSealed() Object.isFrozen()
对象继承
ES5新增了对象继承的方法Object.create,他可以指定新创建的对象是从哪个对象创建而来,如果该方法未指定第一个参数,则默认就是Object.prototype,如果第一个参数是null,则新对象不继承任何对象。
var object = Object.create(Object.prototype); //same as {} or new Object()
该方法第二个参数是定义的新的属性,定义方式同Object.defineProperties.
var person = {alive: true}; var cody = Object.create(person, { name: { configurable: true, enumerable: true, writeable: true, value: ‘cody‘ } }); console.log(cody.alive); //logs true //because console.log(Object.getPrototypeOf(cody).alive); //logs true
获取对象原型
ES5新增加了标准的访问对象原型的方法,Object.getPrototypeOf,而此前的方法是非标准的__proto__.
Object.getPrototypeOf(new Object(‘foo‘)) === String.prototype //return true
函数的上下文
在ES3中年,使用函数的apply,call来定义函数的上下文,而在ES5中有了新的方法bind.
var myObject = {foo:‘foo‘}; var myFunction = function(){ //note I am logging this and arguments here console.log(this,arguments[0],arguments[1],arguments[2]); }; var usingBind = myFunction.bind(myObject,1,2,3); //create new function //when usingBind() is called the this reference, references myObject usingBind(); //logs {foo="foo"} 1 2 3 //Note, that any additional argumetns sent to bind, are also sent to the original function, i.e. the 1 2 4
(完)