
目的
当然是系统学习es6啦。。。并快速了解es6的新特性,并未过多深入。想通过二八定律先全面了解ES6的新特性。
es6简介
简单总结下相关知识点。
es6是什么?
ES6 既是一个历史名词,也是一个泛指,含义是 5.1 版以后的 JavaScript 的下一代标准,涵盖了 ES2015、ES2016、ES2017 等等,而 ES2015 则是正式名称,特指该年发布的正式版本的语言标准。本书中提到 ES6 的地方,一般是指 ES2015 标准,但有时也是泛指“下一代 JavaScript 语言”。
如何查看浏览器兼容性?
各大浏览器的最新版本,对 ES6 的支持可以查看。随着时间的推移,支持度已经越来越高了,超过 90%的 ES6 语法特性都实现了。
nodejs如何查看
Node 是 JavaScript 的服务器运行环境(runtime)。它对 ES6 的支持度更高。除了那些默认打开的功能,还有一些语法功能已经实现了,但是默认没有打开。使用下面的命令,可以查看 Node 已经实现的 ES6 特性。
$ node --v8-options | grep harmony
上面命令的输出结果,会因为版本的不同而有所不同。
转码器
考虑到有可能部分浏览器对es6兼容性可能存在问题,所以有时候需要将es6转成es5,去解决兼容性问题。
Babel 转码器
Babel 是一个广泛使用的 ES6 转码器,可以将 ES6 代码转为 ES5 代码,从而在现有环境执行。这意味着,你可以用 ES6 的方式编写程序,又不用担心现有环境是否支持。下面是一个例子。
// 转码前
input.map(item => item + 1);
// 转码后
input.map(function (item) {
return item + 1;
});
上面的原始代码用了箭头函数,Babel 将其转为普通函数,就能在不支持箭头函数的 JavaScript 环境执行了。
Babel 默认只转换新的 JavaScript 句法(syntax),而不转换新的 API,比如Iterator、Generator、Set、Maps、Proxy、Reflect、Symbol、Promise等全局对象,以及一些定义在全局对象上的方法(比如Object.assign)都不会转码。
举例来说,ES6 在Array对象上新增了Array.from方法。Babel 就不会转码这个方法。
Traceur 转码器
Google 公司的Traceur转码器,也可以将 ES6 代码转为 ES5 代码。
此处不展开深究,有兴趣的自行了解 Traceur Transcoding Demo
let 和 const 关键字
let 关键字
ES6 新增了let关键字,用来声明变量。它的用法类似于var,但是所声明的变量,只在let关键字所在的代码块内有效。
应用场景
for循环的计数器,就很合适使用let命令。
for (let i = 0; i < 10; i++) {
// ...
}
console.log(i);
// ReferenceError: i is not defined
上面代码中,计数器i只在for循环体内有效,在循环体外引用就会报错。
ES6 的块级作用域
let 实际上为 JavaScript 新增了块级作用域。
function f1() {
let n = 5;
if (true) {
let n = 10;
}
console.log(n); // 5
}
块级作用域的出现,实际上使得获得广泛应用的立即执行函数表达式(IIFE)不再必要了。
// IIFE 写法
(function () {
var tmp = ...;
...
}());
// 块级作用域写法
{
let tmp = ...;
...
}
const 关键字
const声明一个只读的常量。
- 一旦声明,常量的值就不能改变。
- 一旦声明变量,就必须立即初始化,不能留到以后赋值。
const的作用域与let命令相同:只在声明所在的块级作用域内有效。const声明的常量,也与let一样不可重复声明。
应用场景
const PI = 3.1415;
console.log(PI) // 3.1415
PI = 3;
// TypeError: Assignment to constant variable.
变量的解构赋值
ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring)。
数组解构
下面是数组赋值并且交换值的例子
//ES6
let list = [ 1, 2, 3 ];
let [ a, , b ] = list ; // a=1 ,b=3
[ b, a ] = [ a, b ] ;//a=3,b=1
//ES5
var list = [ 1, 2, 3 ];
var a = list[0], b = list[2];
var tmp = a; a = b; b = tmp;
对象的解构赋值
//ES6
let { foo, bar } = { foo: "aaa", bar: "bbb" };
foo //aaa
bar //bbb
//ES5
var tmp = { foo: "aaa", bar: "bbb" };
var foo = tmp.foo; //aaa
var bar = tmp.bar; //bbb
字符串的解构赋值
//ES6
const [a,b,c,d,e] = 'hello';
a //h
b //e
c //l
d //l
e //o
/*
类似数组的对象都有一个length属性,因此还可以对这个属性解构赋值。
(然而个人觉得貌似没啥用啊,至少这个应用场景会很少,先了解下即可)
*/
let {length : len} = 'hello';
len // 5
//ES5
var hello ='hello';
var a,b,c,d,e;
a=hello[0];
b=hello[1];
c=hello[2];
d=hello[3];
e=hello[4];
a //h
b //e
c //l
d //l
e //o
/*
对应ES6 获取数组长度
*/
var len = hello.length;
len //5
函数参数的解构赋值
//ES6
function f ([ name, val ]) {
console.log(name, val)
}
function g ({ name: n, val: v }) {
console.log(n, v)
}
function h ({ name, val }) {
console.log(name, val)
}
f([ "bar", 42 ])
g({ name: "foo", val: 7 })
h({ name: "bar", val: 42 })
//ES5
function f (arg) {
var name = arg[0];
var val = arg[1];
console.log(name, val);
};
function g (arg) {
var n = arg.name;
var v = arg.val;
console.log(n, v);
};
function h (arg) {
var name = arg.name;
var val = arg.val;
console.log(name, val);
};
f([ "bar", 42 ]);
g({ name: "foo", val: 7 });
h({ name: "bar", val: 42 });
应用场景
交换变量值
let x = 1;
let y = 2;
[x, y] = [y, x];
函数返回多个返回值
函数只能返回一个值,如果要返回多个值,只能将它们放在数组或对象里返回。有了解构赋值,取出这些值就非常方便。
// 返回一个数组
function example() {
return [1, 2, 3];
}
let [a, b, c] = example();
// 返回一个对象
function example() {
return {
foo: 1,
bar: 2
};
}
let { foo, bar } = example();
函数参数的定义
解构赋值可以方便地将一组参数与变量名对应起来。 56
// 参数是一组有次序的值 实际应用场景很少用
function f([x, y, z]) { ... }
f([1, 2, 3]);
// 参数是一组无次序的值 实际应用场景非常有用
function f({x, y, z}) { ... }
f({z: 3, y: 2, x: 1});
提取 JSON 数据
let jsonData = {
id: 42,
status: "OK",
data: [867, 5309]
};
let { id, status, data: number } = jsonData; //非常有用,rn+redux项目就是这样获取数据绑定视图层展示的
console.log(id, status, number);
// 42, "OK", [867, 5309]
函数参数的默认值
//ES6
function test (_params='default value',_async=true,_callback=function(){}){
}
//ES5
function test(_params,_async,_callback){
if(_params===''|| _params===null|| _params===undefined) _params='default value';
if(_async===''|| _async===null|| _async===undefined) _async=true;
if(_callback===''||_callback===null||_callback===undefined) _callback=function(){};
}
New Built-In Methods(ES6的新支持函数)
Object Property Assignment (浅拷贝)
Object.assign方法用于对象的合并,将源对象( source )的所有可枚举属性,复制到目标对象( target )。
注意:
- 如果目标对象与源对象有同名属性,或多个源对象有同名属性,则后面的属性会覆盖前面的属性。(克隆对象)
Object.assign()只是一级属性复制,比浅拷贝多深拷贝了一层而已。用的时候,还是要注意这个问题的。
//ES6
let dest = { quux: 0 }
let src1 = { foo: 1, bar: 2 }
let src2 = { foo: 3, baz: 4 }
Object.assign(dest, src1, src2)
//dest.quux === 0
//dest.foo === 3
//dest.bar === 2
//dest.baz === 4
//ES5
var dest = { quux: 0 };
var src1 = { foo: 1, bar: 2 };
var src2 = { foo: 3, baz: 4 };
Object.keys(src1).forEach(function(k) {
dest[k] = src1[k];
});
Object.keys(src2).forEach(function(k) {
dest[k] = src2[k];
});
//dest.quux === 0;
//dest.foo === 3;
//dest.bar === 2;
//dest.baz === 4;
Array Element Finding (数组查找)
数组查找新增函数
//ES6
[ 1, 3, 4, 2 ].find(x => x > 3) // 4
[ 1, 3, 4, 2 ].findIndex(x => x > 3) // 2
//ES5
[ 1, 3, 4, 2 ].filter(function (x) { return x > 3; })[0]; // 4
// no equivalent in ES5
String Repeating (字符串重复)
感觉没啥应用场景,暂时想不到,join倒是以前常用,将数组拼接的html模板join成字符串。
//ES6
" ".repeat(4 * depth)
"foo".repeat(3)
//ES5
//能想到这种方式做字符串拷贝的也是 6666666
Array((4 * depth) + 1).join(" ");
Array(3 + 1).join("foo");
String Searching (字符串查找)
Es6 提供了新的函数进行字符串查找,第二个参数为字符串出现的index
//ES6
"hello".startsWith("ello", 1) // true
"hello".endsWith("hell", 4) // true
"hello".includes("ell") // true
"hello".includes("ell", 1) // true
"hello".includes("ell", 2) // false
//ES5
"hello".indexOf("ello") === 1; // true
"hello".indexOf("hell") === (4 - "hell".length); // true
"hello".indexOf("ell") !== -1; // true
"hello".indexOf("ell", 1) !== -1; // true
"hello".indexOf("ell", 2) !== -1; // false
Number Type Checking (数值校验)
//ES6
Number.isNaN(42) === false
Number.isNaN(NaN) === true
Number.isFinite(Infinity) === false
Number.isFinite(-Infinity) === false
Number.isFinite(NaN) === false
Number.isFinite(123) === true
//ES5
var isNaN = function (n) {
return n !== n;
};
var isFinite = function (v) {
return (typeof v === "number" && !isNaN(v) && v !== Infinity && v !== -Infinity);
};
isNaN(42) === false;
isNaN(NaN) === true;
isFinite(Infinity) === false;
isFinite(-Infinity) === false;
isFinite(NaN) === false;
isFinite(123) === true;
Number Safety Checking (数值范围校验)
校验数值是否在一个安全的范围内
//ES6
Number.isSafeInteger(42) === true
Number.isSafeInteger(9007199254740992) === false
//ES5
function isSafeInteger (n) {
return (
typeof n === 'number'
&& Math.round(n) === n
&& -(Math.pow(2, 53) - 1) <= n
&& n <= (Math.pow(2, 53) - 1)
);
}
isSafeInteger(42) === true;
isSafeInteger(9007199254740992) === false;
Number Comparison (数值比较)
ES6的Number对象新增了一个常量Number.EPSILON。这个值很小。引入这么小的一个常量的目的在于,为浮点数计算设置一个误差范围。因为浮点数的计算是不精确的。如果误差小于Number.EPSILON,我们就可以认为得到了正确的结果。
// 举个例子吧:
0.1+0.2; //0.30000000000000004
0.1+0.2-0.3; //5.551115123125783e-17
(0.1+0.2-0.3).toFixed(20); //"0.00000000000000005551"
// 那么我们再来看看0.1+0.2-0.3的值是否小于Number.EPSILON,如果小于,返回true,那我们便可以认为结果正确
(0.1+0.2-0.3).toFixed(20)<Number.EPSILON; // true
//当然我觉得不如这样好了 囧
Number.parseFloat((0.1+0.2).toFixed(2))===0.3
Number Truncation
方法会将数字的小数部分去掉,只保留整数部分。
//ES6
console.log(Math.trunc(42.7)) // 42
console.log(Math.trunc( 0.1)) // 0
console.log(Math.trunc(-0.1)) // -0
//ES5
function mathTrunc (x) {
return (x < 0 ? Math.ceil(x) : Math.floor(x));
}
console.log(mathTrunc(42.7)) // 42
console.log(mathTrunc( 0.1)) // 0
console.log(mathTrunc(-0.1)) // -0
Number Sign Determination (确定数字符号)
此函数共有5种返回值, 分别是 1, -1, 0, -0, NaN. 代表的各是正数, 负数, 正零, 负零, NaN。
//ES6
console.log(Math.sign(7)) // 1
console.log(Math.sign(0)) // 0
console.log(Math.sign(-0)) // -0
console.log(Math.sign(-7)) // -1
console.log(Math.sign(NaN)) // NaN
//ES5
function mathSign (x) {
return ((x === 0 || isNaN(x)) ? x : (x > 0 ? 1 : -1));
}
console.log(mathSign(7)) // 1
console.log(mathSign(0)) // 0
console.log(mathSign(-0)) // -0
console.log(mathSign(-7)) // -1
console.log(mathSign(NaN)) // NaN
参考
本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名
最后编辑时间为:2018-05-23 18:16:23