Aitter's Blog

ES5特性介绍

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中不再能声明变量,声明的函数将会变成全局的
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 格式的要求。
  • 第二个参数是一个函数,可以用来对解析过程中得到的属性名值对进行过滤和转换。
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.preventExtensionsObject.sealObject.freeze 函数可以用来保护对象,防止被第三方有意或无意的修改。

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()方法。
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 pre+v })); //32
console.log(arr.reduceRight(function(pre, v, i){ return pre*v })); //15120

Function的扩展

  • 函数中不能出现两个同名的形式参数
  • 不能给函数的caller属性赋值
  • 未指定环境对象而调用函数,this值不会指向window,而是undefined
  • 添加了bind()方法。
  • 规范化了一个函数对象的属性caller,用于指向调用当前函数的函数的引用。
  • prototype是不可枚举的

Function.prototype.bind 用于改变函数在执行时的this指向

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()等方法。

Date.now() 等价于 new Date().getTime()
new Date().toJSON(); //"2016-06-29T01:53:15.560Z"

RegExp对象

在ES3中,使用正则表达式字面量时共享一个RegExp实例,
而在ES5中,每次使用正则表达式字面量时都要创建新的RegExp实例,就像使用RegExp构造函数一样。

/cat/g 等价于 new RegExp("cat", "g");

相关阅读:
深入探讨 ECMAScript 规范第五版