Posts ES6转ES5
Post
Cancel

ES6转ES5

用 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 转换类数组对象或列表(例如 argumentsNodeListDOMTokenList(由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.

This post is licensed under CC BY 4.0 by the author.
Trending Tags

Trending Tags