这是我组织的 ES6 特性分享的预热篇,主要介绍 ES5 的特性。
既是入门,又是回顾
相信很多人还没有完全在项目中使用
2011
年正式发布的IE9
实现了几乎所有ES5
的特性ES6
,ES7
……都已经或将要来了
ES5 中最有用的特性:JSON
JSON 简介
- Douglas Crockford 在 2002 年创建,
- JSON JavaScript 对象标记(Notation)
- JavaScript 语言的一个子集
- 一种轻量级的数据交换格式
- 易于人阅读和编写,同时也易于机器解析和生成。
那段不堪回首的过去
1 | var data = eval('(' + response + ')'); |
或
1 | <script src="/javascript/json2.js"></script> |
JSON.stringify(value[, replacer [, space]])
1 | var obj = { a: 'x', b: { c: 1 } }; |
JSON.parse(text[, reviver])
1 | //将字符串解析成JSON对象 |
JSON 用法举例
- 解析 JSON 格式的 AJAX 响应
- localStorage,sessionStorage 只能存储字符串
- PHP 使用 SpiderMonkey 引擎创建 JS 上下并输入数据
JSON 的替代协议 Protocol Buffers
JSON 的替代协议 MessagePack
ES5 中最强大的特性:Object 扩展
以下是 ES5 对 Object 对象的所有扩展
1 | Object.defineProperty |
Object.defineProperty(obj, prop, descriptor)
直接在一个对象上定义一个新属性,或者修改一个已经存在的属性, 并返回这个对象。
1 | var obj = {}; |
Object.defineProperty 数据描述符 configurable
1 | var obj = {}; |
Object.defineProperty 数据描述符 enumerable
1 | var obj = {}; |
使用 Object.defineProperty 调试
1 | function debugObject(obj, key){ |
在 ES7 草案中,还有一个方法Object.observe(ob, callback)
可以更加方便地监听对象变化。
Object.defineProperties(obj, props)
添加或修改 1+个属性,并返回该对象。
1 | var obj = {}; |
Object.create(prototype, descriptors)
1 | var Man = { |
Object.create(prototype, descriptors)
1 | var obj = Object.create(null); |
Object.getOwnPropertyDescriptor(obj, prop) 获取属性描述符
1 | var obj = { a: 1 }; |
Object.getOwnPropertyNames(obj) 获取所有自有属性名
获取所有自有属性名,包含可枚举以及不可枚举的,但是不包含原型链上的。
1 | var prototype = { a: 0 }; |
Object.freeze(obj) 冻结一个对象
冻结一个对象,意味着该对象的属性不能增删改,属性的各个特性也不能改。
而Object.isFrozen(obj)
可以用来判断一个对象有没有冻结。
1 | var obj = { key: 'val', key1: {} }; |
怎样完全冻结一个对象
1 | function deepFreeze(obj) { |
Object.seal(obj) 密封一个对象
密封,比冻结宽松一点,仅仅能修改属性的值。
而Object.isSealed(obj)
可以用来判断一个对象有没有密封。
1 | var obj = { key: 'val', key1: {} }; |
Object.preventExtensions(obj) 不能添加新属性
Object.isExtensible
用来检查一个对象能不能添加新属性
1 | var obj = { key: 'val', key1: {} }; |
Object.getPrototypeOf(obj)
1 | function Car() {} |
Array 扩展
Array.isArray(obj)
判断一个对象是不是数组
1 | var array = [1, 2, 3]; |
Array 实例扩展
1 | var array = [1, 2, 2, 3]; |
保留字作为属性名
1 | var obj = { |
使用 get/set 进行属性初始化
1 | var obj = { |
全局 undefined 对象
以前,undefined 对象是这样产生的。
1 | var undef; |
在 ES5 中有了不可变的全局的undefined
对象。
1 | var undefined = 1; |
Function 实例扩展
Function.prototype.bind
fun.bind(thisArg[, arg1[, arg2[, ...]]])
1 | function a() { |
Curry(柯里化)
预先设定函数的前面若干个实参,生成一个接受剩余实参的新函数。
1 | function curry(fn) { |
柯里化案例
1 | model.groups = _.filter(model.groups, function(g) { |
_.curry & _.curryRight
1 | var abc = function(a, b, c) { |
严格模式
把整段代码或某个函数放在严格操作的环境中运行,严格环境有诸多限制:
- 将失误转成异常
- 简化变量的使用
- 让 eval 和 arguments 变的简单
- “安全的” JavaScript
- 为未来的 ECMAScript 版本铺平道路
严格模式:将失误转成异常
- 意外地创建全局变量
1 | (function() { |
- 不再静默失败,而是抛出异常
1 | var fixed = {}; |
- 形参命名不能重复
1 | (function(a, a){'use strict'; })(); //SyntaxError |
注意:严格模式下,ES5 中定义变量时,字段名也不能重复,但是 ES6 又允许了。
- 严格模式禁止八进制数字语法
1 | //FireFox: SyntaxError, Chrome/IE10: SyntaxError |
严格模式:简化变量的使用
- 禁用
with
1 | (function(){ |
eval
不再为上层作用域引入新变量
1 | (function() { |
严格模式:简化变量的使用
call
&apply
对this
的修改规则简化
1 | (function() { |
- 不能使用
caller
和callee
1 | (function restricted(a) { |
其他小的特性
1. Date.prototype.toISOString
转换成 YYYY-MM-DDTHH:mm:ss.sssZ
这种格式
2. Date.now()
和 new Date().getTime()
一样。
3. String.prototype.trim
和$.trim
,_.trim
一样。
4. 把字符串当做数组一样访问
1 | 'foobar'[1] === 'o'; // true |
5. parseInt 忽略前置 0
1 | parseInt('012'); // 12,在ES3中,因为前置0而按照八进制解析成10 |
思考题
- 以下这种情况是为什么?
1 | var array = []; |