用 ES5 实现 ES6 的特性。
Babel 在线转换
去 Babel 中文网 尝试一下吧。
箭头函数
与函数表达式相比,箭头函数(也称为胖箭头函数)具有更短的语法,并且词法绑定 this。箭头功能始终是匿名的。
ES6
1
2
[1, 2, 3].map((n) => n * 2);
// -> [ 2, 4, 6 ]
ES5
1
2
3
4
[1, 2, 3].map(function (n) {
return n * 2;
}, this);
// -> [ 2, 4, 6 ]
ES6
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
var evens = [2, 4, 6, 8, 10];
// Expression bodies
var odds = evens.map((v) => v + 1);
var nums = evens.map((v, i) => v + i);
console.log(odds);
// -> [3, 5, 7, 9, 11]
console.log(nums);
// -> [2, 5, 8, 11, 14]
// Statement bodies
var fives = [];
nums = [1, 2, 5, 15, 25, 32];
nums.forEach((v) => {
if (v % 5 === 0) {
fives.push(v);
}
});
console.log(fives);
// -> [5, 15, 25]
// Lexical this
var bob = {
_name: "Bob",
_friends: [],
printFriends() {
this._friends.forEach((f) => console.log(this._name + " knows " + f));
},
};
ES5
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
"use strict";
var evens = [2, 4, 6, 8, 10];
// Expression bodies
var odds = evens.map(function (v) {
return v + 1;
}, this);
var nums = evens.map(function (v, i) {
return v + i;
}, this);
console.log(odds);
// -> [3, 5, 7, 9, 11]
console.log(nums);
// -> [2, 5, 8, 11, 14]
var fives = [];
nums = [1, 2, 5, 15, 25, 32];
// Statement bodies
nums.forEach(function (v) {
if (v % 5 === 0) {
fives.push(v);
}
}, this);
console.log(fives);
// -> [5, 15, 25]
// Lexical this
var bob = {
_name: "Bob",
_friends: [],
printFriends: function printFriends() {
this._friends.forEach(function (f) {
return console.log(this._name + " knows " + f);
}, this);
},
};
块级作用域
块级作用域提供除函数和顶级作用域之外的作用域。这可以确保你的变量不会泄漏到它们定义的范围之外。
ES6
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// let 定义了块作用域变量, 可以选择赋值
"use strict";
var a = 5;
var b = 10;
if (a === 5) {
let a = 4; // The scope is inside the if-block
var b = 1; // The scope is inside the function
console.log(a); // 4
console.log(b); // 1
}
console.log(a); // 5
console.log(b); // 1
ES5
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
"use strict";
var a = 5;
var b = 10;
if (a === 5) {
// 技术上利用了立即执行函数
(function () {
var a = 4;
b = 1;
console.log(a); // 4
console.log(b); // 1
})();
}
console.log(a); // 5
console.log(b); // 1
ES6
1
2
3
4
5
6
7
8
9
"use strict";
const favorite = 7;
// Attempt to overwrite the constant
try {
favorite = 15;
} catch (err) {
console.log("my favorite number is still: " + favorite);
}
ES5
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
"use strict";
// define favorite as a non-writable `constant`
// and give it the value 7
Object.defineProperties(window, {
favorite: {
value: 7,
enumerable: true,
},
});
// descriptors are by default false and const are enumerable
var favorite = 7;
// Attempt to overwrite the constant
favorite = 15;
console.log("my favorite number is still: " + favorite);
模板字符串
模板字符串支持中间插值。
ES6
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
var person = "Addy Osmani";
console.log(`Yo! My name is ${person}!`);
var user = { name: "Caitlin Potter" };
console.log(`Thanks for getting this into V8, ${user.name}.`);
var a = 50;
var b = 100;
console.log(`The number of JS frameworks is ${a + b} and not ${2 * a + b}.`);
// 不用使用 \n 即可实现多行字符串
console.log(`string text line 1
string text line 2`);
// 支持函数
function fn() {
return "result";
}
console.log(`foo ${fn()} bar`);
ES5
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
"use strict";
var person = "Addy Osmani";
console.log("Yo! My name is " + person + "!");
var user = { name: "Caitlin Potter" };
console.log("Thanks for getting this into V8, " + user.name + ".");
var a = 50;
var b = 100;
console.log(
"The number of JS frameworks is " + (a + b) + " and not " + (2 * a + b) + "."
);
console.log("string text line 1\nstring text line 2");
// Or, alternatively:
console.log(
"string text line 1\n\
string text line 2"
);
function fn() {
return "result";
}
console.log("foo " + fn() + " bar");
计算属性名
计算属性名允许你在对象中使用表达式进行属性名定义。
ES6
1
2
3
4
5
6
7
8
9
10
var prefix = "foo";
var myObject = {
[prefix + "bar"]: "hello",
[prefix + "baz"]: "world",
};
console.log(myObject["foobar"]);
// -> hello
console.log(myObject["foobaz"]);
// -> world
ES5
1
2
3
4
5
6
7
8
9
10
11
12
"use strict";
var prefix = "foo";
var myObject = {};
myObject[prefix + "bar"] = "hello";
myObject[prefix + "baz"] = "world";
console.log(myObject["foobar"]);
// -> hello
console.log(myObject["foobaz"]);
// -> world
解构赋值
解构赋值是一个 JS 表达式语法, 让你可以从数组或者对象中提取数据。
ES6
1
2
3
var { foo, bar } = { foo: "lorem", bar: "ipsum" };
// foo => lorem
// bar => ipsum
ES5
1
2
3
4
5
6
"use strict";
var _ref = { foo: "lorem", bar: "ipsum" };
var foo = _ref.foo;
var bar = _ref.bar;
ES6
1
var [a, , b] = [1, 2, 3];
ES6 (shimming using Symbol.iterator
):
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
"use strict";
var _slicedToArray = function (arr, i) {
if (Array.isArray(arr)) {
return arr;
} else {
var _arr = [];
for (
var _iterator = arr[Symbol.iterator](), _step;
!(_step = _iterator.next()).done;
) {
_arr.push(_step.value);
if (i && _arr.length === i) {
break;
}
}
return _arr;
}
};
var _ref = [1, 2, 3];
var _ref2 = _slicedToArray(_ref, 3);
var a = _ref2[0];
var b = _ref2[2];
ES5
1
2
3
4
5
6
7
8
9
10
11
12
13
String.prototype.asNamedList = function () {
return this.split(/\s*,\s*/)
.map(function (name, i) {
return name
? "var " + name + "=slice(" + i + ", " + (i + 1) + ")[0]"
: "";
})
.join(";");
};
with ([1, 2, 3]) {
eval("a, , b".asNamedList());
}
默认参数
默认参数允许让你的函数拥有可选的参数, 不必检测 arguments.length
或者 undefined
。
ES6
1
2
3
4
5
6
7
8
function greet(msg = "hello", name = "world") {
console.log(msg, name);
}
greet();
// -> hello world
greet("hey");
// -> hey world
ES5
1
2
3
4
5
6
7
8
9
10
11
12
13
"use strict";
function greet() {
var msg = arguments[0] === undefined ? "hello" : arguments[0];
var name = arguments[1] === undefined ? "world" : arguments[1];
console.log(msg, name);
}
function greet(msg, name) {
msg === undefined && (msg = "hello");
name === undefined && (name = "world");
console.log(msg, name);
}
ES6
1
2
3
4
5
function f(x, y = 12) {
return x + y;
}
f(3) === 15;
ES5
1
2
3
4
5
6
7
8
9
10
11
"use strict";
function f(x, y) {
if (y === undefined) {
y = 12;
}
return x + y;
}
f(3) === 15;
迭代器和 for...of
迭代器是可以遍历的对象。
使用 for..of
循环迭代:
ES6
1
2
3
4
5
// 在背后,这将从数组中获取一个迭代器并循环遍历它,从中获取值。
for (let element of [1, 2, 3]) {
console.log(element);
}
// => 1 2 3
ES6 (如果支持 Symbol
,则不使用 for-of
)
1
2
3
4
5
6
7
8
9
10
11
"use strict";
for (
var _iterator = [1, 2, 3][Symbol.iterator](), _step;
!(_step = _iterator.next()).done;
) {
var element = _step.value;
console.log(element);
}
// => 1 2 3
ES5 (近似):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 使用 forEach(),不需要在包含中声明索引和元素变量范围。
// 它们作为参数提供给迭代器,并且仅限于迭代当次
var a = [1, 2, 3];
a.forEach(function (element) {
console.log(element);
});
// => 1 2 3
// 使用 for 循环
var a = [1, 2, 3];
for (var i = 0; i < a.length; ++i) {
console.log(a[i]);
}
// => 1 2 3
类
这实现了 ES6 草案规范中描述的类语法和语义。类是重用代码的好方法。几个 JS 库提供类和继承,但它们不相互兼容。
ES6
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
class Hello {
constructor(name) {
this.name = name;
}
hello() {
return "Hello " + this.name + "!";
}
static sayHelloAll() {
return "Hello everyone!";
}
}
class HelloWorld extends Hello {
constructor() {
super("World");
}
echo() {
console.log(super.hello()); // Hello World!
}
}
var hw = new HelloWorld();
hw.echo();
console.log(Hello.sayHelloAll()); // Hello everyone!
console.log(HelloWorld.sayHelloAll()); // Hello everyone!
ES5 (近似)
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
function Hello(name) {
this.name = name;
}
Hello.prototype.hello = function hello() {
return "Hello " + this.name + "!";
};
Hello.sayHelloAll = function () {
return "Hello everyone!";
};
function HelloWorld() {
Hello.call(this, "World");
}
HelloWorld.prototype = Object.create(Hello.prototype);
HelloWorld.prototype.constructor = HelloWorld;
HelloWorld.sayHelloAll = Hello.sayHelloAll;
HelloWorld.prototype.echo = function echo() {
console.log(Hello.prototype.hello.call(this)); // Hello World!
};
var hw = new HelloWorld();
hw.echo();
console.log(Hello.sayHelloAll()); // Hello everyone!
console.log(HelloWorld.sayHelloAll()); // Hello everyone!
模块
模块尝试解决依赖关系和部署中的许多问题,允许用户创建具有显式导出的模块,从这些模块导入特定的导出名称,并将这些名称分开。
假设使用 CommonJS
app.js - ES6
1
2
import math from "lib/math";
console.log("2π = " + math.sum(math.pi, math.pi));
app.js - ES5
1
2
var math = require("lib/math");
console.log("2π = " + math.sum(math.pi, math.pi));
lib/math.js - ES6
1
2
3
4
export function sum(x, y) {
return x + y;
}
export var pi = 3.141593;
lib/math.js - ES5
1
2
3
4
5
exports.sum = sum;
function sum(x, y) {
return x + y;
}
var pi = (exports.pi = 3.141593);
lib/mathplusplus.js - ES6
1
2
3
4
5
export * from "lib/math";
export var e = 2.71828182846;
export default function (x) {
return Math.exp(x);
}
lib/mathplusplus.js - ES5
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
var Math = require("lib/math");
var _extends = function (target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) {
target[key] = source[key];
}
}
return target;
};
var e = (exports.e = 2.71828182846);
exports["default"] = function (x) {
return Math.exp(x);
};
module.exports = _extends(exports["default"], exports);
数字字面量
ES6
1
2
3
4
5
const binary = [0b0, 0b1, 0b11];
console.assert(binary === [0, 1, 3]);
const octal = [0o0, 0o1, 0o10, 0o77];
console.assert(octal === [0, 1, 8, 63]);
ES5
1
2
3
4
5
6
7
"use strict";
var binary = [0, 1, 3];
console.assert(binary === [0, 1, 3]);
var octal = [0, 1, 8, 63];
console.assert(octal === [0, 1, 8, 63]);
对象方法
对象方法设定支持所直接写方法,例如 toString()
。
ES6
1
2
3
4
5
6
7
8
9
const object = {
value: 42,
toString() {
return this.value;
},
};
console.log(object.toString() === 42);
// -> true
ES5
1
2
3
4
5
6
7
8
9
10
11
"use strict";
var object = {
value: 42,
toString: function toString() {
return this.value;
},
};
console.log(object.toString() === 42);
// -> true
对象初始化简写
这允许您在对象中的属性名称和属性值相同时不需要重复。
ES6
1
2
3
4
5
6
7
8
9
10
11
12
13
14
function getPoint() {
var x = 1;
var y = 10;
return { x, y };
}
console.log(
getPoint() ===
{
x: 1,
y: 10,
}
);
ES5
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
"use strict";
function getPoint() {
var x = 1;
var y = 10;
return { x: x, y: y };
}
console.log(
getPoint() ===
{
x: 1,
y: 10,
}
);
剩余参数
rest 参数允许您的函数具有可变数量的参数,而无需使用 arguments 对象。 rest 参数是 Array 的一个实例,因此所有数组方法都可以正常工作。
ES6
1
2
3
4
5
6
7
function f(x, ...y) {
// y is an Array
return x * y.length;
}
console.log(f(3, "hello", true) === 6);
// -> true
ES5
1
2
3
4
5
6
7
8
9
10
11
12
"use strict";
function f(x) {
var y = [];
y.push.apply(y, arguments) && y.shift();
// y is an Array
return x * y.length;
}
console.log(f(3, "hello", true) === 6);
// -> true
展开运算符
扩展运算符与剩余参数相反。 它允许您将数组扩展为多个形式参数。
ES6
1
2
3
4
5
6
7
8
function add(a, b) {
return a + b;
}
let nums = [5, 4];
console.log(add(...nums));
// -> 9
ES5
1
2
3
4
5
6
7
8
9
10
11
12
"use strict";
var _toArray = function (arr) {
return Array.isArray(arr) ? arr : [].slice.call(arr);
};
function add(a, b) {
return a + b;
}
var nums = [5, 4];
console.log(add.apply(null, _toArray(nums)));
ES6
1
2
3
4
5
function f(x, y, z) {
return x + y + z;
}
// 将每个数组元素作为参数传递
f(...[1, 2, 3]) === 6;
ES5
1
2
3
4
5
6
"use strict";
function f(x, y, z) {
return x + y + z;
}
f.apply(null, [1, 2, 3]) === 6;
代理函数对象
ES6
1
2
3
4
5
6
7
8
9
10
11
12
13
var target = function () {
return "I am the target";
};
var handler = {
apply(target, ...args) {
return "I am the proxy";
},
};
var p = new Proxy(target, handler);
console.log(p() === "I am the proxy");
// -> true
ES5
在 ES5 中没有代理。
类数组对象转为数组
Array.from 转换类数组对象或列表(例如 arguments
、NodeList
、DOMTokenList
(由classList
使用)、NamedNodeMap
(由 attributes 属性使用)成为真正的数组,并返回这个数组。
ES6
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const listFriends = function () {
const friends = Array.from(arguments);
friends.forEach((friend) => {
console.log(friend);
});
};
listFriends("ann", "bob");
// -> 'ann'
// -> 'bob'
const divs = document.querySelectorAll("div");
Array.from(divs).forEach((node) => {
console.log(node);
});
// -> <div>...</div>
// -> <div>...</div>
ES5
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var listFriends = function () {
var friends = [].slice.call(arguments);
friends.forEach(function (friend) {
console.log(friend);
});
};
listFriends("ann", "bob");
// -> 'ann'
// -> 'bob'
var divsArray = [].slice.call(document.querySelectorAll("div"));
divsArray.forEach(function (node) {
console.log(node);
});
// -> <div>...</div>
// -> <div>...</div>
关于
启发自
License
原文地址:https://github.com/addyosmani/es6-equivalents-in-es5
This work is licensed under a Creative Commons Attribution 4.0 International License.