- 原文做者:Addy Osmani
- 原文連接: es6-equivalents-in-es5
- 譯者:snow
- 喜歡理由:幫助咱們更好的瞭解 ES6 語法
與函數表達式相比,箭頭函數表達式(也稱爲胖箭頭函數)的語法更簡介,而且不會建立本身的
this
。
箭頭函數至關於匿名函數。node
ES6:git
[1, 2, 3].map(n => n * 2);
// -> [ 2, 4, 6 ]
複製代碼
ES5 實現:es6
[1, 2, 3].map(function(n) { return n * 2; }, this);
// -> [ 2, 4, 6 ]
複製代碼
ES6:github
var evens = [2, 4, 6, 8, 10];
// 表達式正文
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]
// 聲明式正文
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]
// 做用域中的 this
var bob = {
_name: 'Bob',
_friends: [],
printFriends() {
this._friends.forEach(f =>
console.log(this._name + ' knows ' + f));
}
}
複製代碼
ES5:api
'use strict';
var evens = [2, 4, 6, 8, 10];
// 表達式正文
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];
// 聲明式正文
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:bash
// let 聲明一個局部塊做用域,在 ES6 中能夠任意的初始化一個值
'use strict';
var a = 5;
var b = 10;
if (a === 5) {
let a = 4; // 做用域在 if 塊中
var b = 1; // 做用域在函數內部
console.log(a); // 4
console.log(b); // 1
}
console.log(a); // 5
console.log(b); // 1
複製代碼
ES5:babel
'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:app
// const 在 ES6 中建立只讀的屬性常量
'use strict';
// 將 favorite 定義爲常量而且賦值爲 7
const favorite = 7;
// 試圖覆蓋常量
try {
favorite = 15;
} catch (err) {
console.log('my favorite number is still: ' + favorite);
// 仍然會輸出 7
}
複製代碼
ES5:函數
// 將 favorite 定義爲一個不可寫的「常量」,並將其賦值爲 7。
Object.defineProperties(window, {
favorite: {
value: 7,
enumerable: true
}
});
// 屬性描述默認爲 false,而且 const 是可枚舉的
// 試圖覆蓋常量
favorite = 15;
// 仍然會輸出 7
console.log('my favorite number is still: ' + favorite);
複製代碼
ES6 模版字符串是能夠包含嵌入表達式的字符串,有時也被叫作插值表達式。
ES6:
// 表達式佔位符的基本用法
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
string text line 2`);
// 函數內部表達式
function fn() { return 'result'; }
console.log(`foo ${fn()} bar`);
複製代碼
ES5:
'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');
// 或者下面這種寫法
console.log('string text line 1\n\ string text line 2');
// 函數內部表達式
function fn() {
return 'result';
}
console.log('foo ' + fn() + ' bar');
複製代碼
計算屬性名容許你基於表達式在對象文本中指定屬性
ES6:
var prefix = 'foo';
var myObject = {
[prefix + 'bar']: 'hello',
[prefix + 'baz']: 'world'
};
console.log(myObject['foobar']);
// -> hello
console.log(myObject['foobaz']);
// -> world
複製代碼
ES5:
'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
複製代碼
解構賦值語法是一個
JavaScript
表達式,它可使用數組映射和對象文本構造的語法從數組和對象中提取值,對變量進行賦值。
ES6:
var {foo, bar} = {foo: 'lorem', bar: 'ipsum'};
// foo => lorem and bar => ipsum
複製代碼
ES5:
'use strict';
var _ref = { foo: 'lorem', bar: 'ipsum' };
// foo => lorem and bar => ipsum
var foo = _ref.foo;
var bar = _ref.bar;
複製代碼
ES3:
with({foo: 'lorem', bar: 'ipsum'}) {
// foo => lorem and bar => ipsum
}
複製代碼
ES6:
var [a, , b] = [1,2,3];
複製代碼
ES6 (shimming using Symbol.iterator
):
'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:
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());
}
複製代碼
默認參數容許函數具備可選參數,而不須要檢查參數的長度或是否未定義。
ES6:
function greet(msg='hello', name='world') {
console.log(msg,name);
}
greet();
// -> hello world
greet('hey');
// -> hey world
複製代碼
ES5:
'use strict';
function greet() {
// 若是像這樣訪問 arguments[0],則能夠簡單地進行訪問 msg 變量名
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);
}
// 對未定義的參數進行檢查的基本方法
function greet(msg, name) {
console.log(
defaults(msg, 'hello'),
defaults(name, 'world')
);
}
greet();
// -> hello world
greet('hey');
// -> hey world
複製代碼
ES6:
function f(x, y=12) {
// y 的指是 12 若是沒有接收(或者接收的是 undefined )
return x + y;
}
f(3) === 15;
複製代碼
ES5:
'use strict';
function f(x, y) {
if (y === undefined) {
y = 12;
}
return x + y;
}
f(3) === 15;
複製代碼
遍歷器是能夠遍歷容器的對象。這是一種使類工做在
for..of
循環的有用方法。
接口相似於遍歷器接口。
迭代一個for..of
循環的形式以下。
ES6:
// 當前環境,將從數組中獲取一個遍歷器,並對其進行循環,從中獲取值
for (let element of [1, 2, 3]) {
console.log(element);
}
// => 1 2 3
複製代碼
ES6 (without using for-of
, if Symbol
is supported):
'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 (approximates):
// 使用 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
複製代碼
注意
Symbol
的使用。ES5 須要一個正確的Symbol polyfill
才能正常使用。
class
實現了 ES6 規範草案中描述的類語法和語義。
class
是複用代碼最好的方法。
一些 JS 庫提供了類和繼承,但它們並不相互兼容。
ES6:
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() {
alert(super.hello());
}
}
var hw = new HelloWorld();
hw.echo();
alert(Hello.sayHelloAll());
複製代碼
ES5 ( 相似功能 ):
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() {
alert(Hello.prototype.hello.call(this));
};
var hw = new HelloWorld();
hw.echo();
alert(Hello.sayHelloAll());
複製代碼
更詳細的介紹能夠查看 Babel
模塊功能大部分是實現了,一些加載api仍然在改進中。
模塊試圖解決依賴關係和部署中的許多問題,容許用戶使用顯式導出建立模塊,從這些模塊中導入特定的導出名稱,並保持這些名稱的獨立性。
app.js - ES6
import math from 'lib/math';
console.log('2π = ' + math.sum(math.pi, math.pi));
複製代碼
app.js - ES5
var math = require('lib/math');
console.log('2π = ' + math.sum(math.pi, math.pi));
複製代碼
lib/math.js - ES6
export function sum(x, y) {
return x + y;
}
export var pi = 3.141593;
複製代碼
lib/math.js - ES5
exports.sum = sum;
function sum(x, y) {
return x + y;
}
var pi = exports.pi = 3.141593;
複製代碼
lib/mathplusplus.js - ES6
export * from 'lib/math';
export var e = 2.71828182846;
export default function(x) {
return Math.exp(x);
}
複製代碼
lib/mathplusplus.js - ES5
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:
var binary = [
0b0,
0b1,
0b11
];
console.assert(binary === [0, 1, 3]);
var octal = [
0o0,
0o1,
0o10,
0o77
];
console.assert(octal === [0, 1, 8, 63]);
複製代碼
ES5:
'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:
var object = {
value: 42,
toString() {
return this.value;
}
};
console.log(object.toString() === 42);
// -> true
複製代碼
ES5:
'use strict';
var object = {
value: 42,
toString: function toString() {
return this.value;
}
};
console.log(object.toString() === 42);
// -> true
複製代碼
在對象中的屬性名和屬性值相同時能夠忽略屬性值。
ES6:
function getPoint() {
var x = 1;
var y = 10;
return {x, y};
}
console.log(getPoint() === {
x: 1,
y: 10
});
複製代碼
ES5:
'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
參數是數組的一個實例,所以全部的數組方法均可以使用。
ES6:
function f(x, ...y) {
// y 是個數組
return x * y.length;
}
console.log(f(3, 'hello', true) === 6);
// -> true
複製代碼
ES5:
'use strict';
function f(x) {
var y = [];
y.push.apply(y, arguments) && y.shift();
// y 是個數組
return x * y.length;
}
console.log(f(3, 'hello', true) === 6);
// -> true
複製代碼
擴展運算符是和
rest
參數相反的。
它容許將數組展開爲多個形式的參數。
ES6:
function add(a, b) {
return a + b;
}
let nums = [5, 4];
console.log(add(...nums));
複製代碼
ES5:
'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:
function f(x, y, z) {
return x + y + z;
}
// 傳遞數組的每個參數
f(...[1,2,3]) === 6;
複製代碼
ES5:
'use strict';
function f(x, y, z) {
return x + y + z;
}
// 傳遞數組的每個參數
f.apply(null, [1, 2, 3]) === 6;
複製代碼
ES6:
var target = function () {
return 'I am the target';
};
var handler = {
apply: function (receiver, ...args) {
return 'I am the proxy';
}
};
var p = new Proxy(target, handler);
console.log(p() === 'I am the proxy');
// -> true
複製代碼
ES5:
在 ES5 中沒有
proxy
, 沒有相似的方法去攔截。
Array.from 使有着單一的參數類數組或者列表(像:
arguments
,NodeList
,DOMTokenList
(當作classList
),NamedNodeMap
(屬性使用))返回一個新的數組實例。
ES6:
var listFriends = function() {
var friends = Array.from(arguments);
friends.forEach(friend => {
console.log(friend);
});
};
listFriends('ann', 'bob');
// -> 'ann'
// -> 'bob'
var divs = document.querySelectorAll('div');
Array.from(divs).forEach(node => {
console.log(node);
});
// -> <div>...</div>
// -> <div>...</div>
複製代碼
ES5:
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>
複製代碼
若是有錯誤或者錯別字,還請給我留言指出,謝謝。
咱們下期見。