
2011年6月,ECMAscript 5.1版发布,并且成为ISO国际标准,简称ES5。
浏览器支持
IE9+ , Android Browser 4.3+, Safari5.1+, Chrome22+, FireFox20+, Opera12.1+
严格模式
在函数内顶部或模块顶部添加: "use strict";
以开启对该作用域的语法检查。
在严格模式下有以下限制:
- 未声明的变量赋值抛出一个ReferenceError, 而不是创建一个全局变量。
- var定义只能在函数级,if、for、while、switch等不能有var定义
- 一个对象字面量中不能声明两个名称相同的属性。一个函数也不能有名称相同的形式参数。
- arguments
- 不能使用arguments、eval、let、const作为标识符(变量名方法名等)
- 不能修改作为函数内部对象的arguments,因此形式参数和arguments之间不再有同步变化
- 不能访问arguments.callee
- ES5中定义了arguments.caller属性,它的值始终是undefined,主要用于区分arguments.caller和函数的caller,但是不能在严格模式下访问
- 普通的函数调用中this是null
- 试图改变只读属性将会抛出异常
- delete失败会抛出异常
- eval中不再能声明变量,声明的函数将会变成全局的
1 2 3 4 5 6 7 8 9 10
| function f1 (c1, c2){ 'use strict'; var arguments=9; // Unexpected eval or arguments in strict mode console.log(arguments); //[2, 3] console.log(arguments[0]); //2 arguments[0]=12; console.log(arguments[0]); //12 console.log(c1); //2 console.log(arguments.callee);//Uncaught TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed }
|
JSON对象
ES5提供一个全局的JSON对象
JSON.stringify(obj, fn/arr, number) 序列化
- 第一个参数是待转换的 ECMAScript 对象,
- 第二个参数可以是一个函数或是数组。如果是函数,则转换的结果由该函数来确定;如果是数组,则只有出现在数组中的属性名称,才会出现在转换之后的结果中。
- 第三个参数是用来控制转换结果中文本的缩进,以更好的进行显示。
JSON.parse(str, fn) 反序列化
- 第一个参数是 JSON 文本,需要符合 JSON 格式的要求。
- 第二个参数是一个函数,可以用来对解析过程中得到的属性名值对进行过滤和转换。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| var jsonStr = '{"a":1, "b":2, "c":3}'; JSON.parse(jsonStr); JSON.parse(jsonStr, function(key, value) { return typeof value === 'number' ? value * 2 : value; }); // 结果为 {a:2, b:4, c:6} JSON.parse(jsonStr, function(key, value) { return typeof value === 'number' && value % 2 === 0 ? undefined : value; }); // 结果为 {a:1, b:3} var user = { name : 'Alex', password : 'password', email : 'alex@example.org' }; JSON.stringify(user); JSON.stringify(user, ['name']); // 输出结果为“{"name":"Alex"}” JSON.stringify(user, function(key, value) { if (key === 'email') { return '******'; } if (key === 'password') { return undefined; } return value; }); // 输出结果为“{"name":"Alex","email":"******"}” JSON.stringify(user, null, 4); => { "name": "Alex", "password": "password", "email": "alex@example.org" }
|
注意:
JSON.parse()必须接收严格的JSON格式,否则报错,比如键名必须使用双引号括起来
Object的扩展
对象的属性有了更多的控制
- 继承相关方法:create()、getPrototypeOf()
- 属性相关方法:defineProperty()、defineProperties()、getOwnPropertyDescriptor()、getOwnPropertyNames()、keys()
- 防篡改方法:preventExtensions()、isExtensible()、seal()、isSealed()、freeze()、isFrozen()
Object.preventExtensions、Object.seal 和 Object.freeze 函数可以用来保护对象,防止被第三方有意或无意的修改。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| var cat = {}; Object.defineProperty(cat, "name", { value: "Maru", writable: false, enumerable: true, configurable: false }); Object.defineProperty(cat, "skill", { value: "exploring boxes", writable: true, enumerable: true, configurable: true }); var obj = {}; Object.defineProperty(obj, 'val', {}); // 创建一个新属性,特性为默认值 obj.val = 1; Object.defineProperty(obj, 'CONSTANT', {value : 32, writable : false}); // 创建一个只读属性 obj.CONSTANT = 16; // 对属性的修改是无效的,但是不会抛出错误 Object.defineProperty(obj, "newVal", {enumerable: true}); for (var key in obj) { console.log(key); // 可以枚举出 newVal } var initValue = 0; Object.defineProperty(obj, "initValue", { get : function() { return initValue; }, set : function(val) { if (val > 0) { initValue = val; } } }); var obj = {val : 1}; obj.newVal = "Hello"; Object.seal(obj); Object.defineProperty(obj, 'anotherVal', {}); // 抛出 TypeError 错误
|
Array的扩展
扩展的迭代或缩小方法都不会改变原有的数组,只会返回处理后的新数组。
- 判断方法:添加了静态方法Array.isArray(obj)用于判断obj是否为一个Array对象的实例。
- 索引方法:添加了两个用于查找指定项索引的方法indexOf()和lastIndexOf()。查找时使用全等(===)进行匹配。
- 迭代方法:添加了every()、some()、forEach()、map()、filter()方法。
- 缩小方法:添加了reduce()和reduceRight()方法。
1 2 3 4 5 6 7 8 9 10
| var arr = [2,9,4,5,3,7,2]; console.log(Array.isArray(arr)); //true console.log(arr.indexOf(2)); //0 console.log(arr.lastIndexOf(2)); //6 console.log(arr.every(function(v,i){ return v > 1 })); //true console.log(arr.some(function(v,i){ return v>6 })); //true console.log(arr.map(function(v,i){ return v>5 })); //[false, true, false, false, false, true, false] console.log(arr.filter(function(v,i){ return v>6 })); //[9, 7] console.log(arr.reduce(function(pre, v, i){ return res+v })); //32 console.log(arr.reduceRight(function(pre, v, i){ return res*v })); //15120
|
Function的扩展
- 函数中不能出现两个同名的形式参数
- 不能给函数的caller属性赋值
- 未指定环境对象而调用函数,this值不会指向window,而是undefined
- 添加了bind()方法。
- 规范化了一个函数对象的属性caller,用于指向调用当前函数的函数的引用。
- prototype是不可枚举的
Function.prototype.bind
用于改变函数在执行时的this指向
1 2 3 4 5 6 7
| var obj = { name : "alex" }; function func() { console.log(this.name); } var func1 = func.bind(obj)(); // alex
|
String的扩展
添加了trim()方法 String.prototype.trim
Date的扩展
添加了Date.now()、Date.prototype.toJSON()等方法。
1 2 3
| Date.now() 等价于 new Date().getTime() new Date().toJSON(); //"2016-06-29T01:53:15.560Z"
|
RegExp对象
在ES3中,使用正则表达式字面量时共享一个RegExp实例,
而在ES5中,每次使用正则表达式字面量时都要创建新的RegExp实例,就像使用RegExp构造函数一样。
1
| /cat/g 等价于 new RegExp("cat", "g");
|
相关阅读:
深入探讨 ECMAScript 规范第五版