es6部分新特性(箭头函数,对象属性的简洁表达式,Symbol)
箭头函数
传统函数
传统函数有两种表达方式,一种是函数声明,另一种是函数表达式。
函数声明格式如下:
function Person(){}
函数表达式格式如下:
const Person = function (){}
这两种示例的函数都有构造函数,前者有name属性。后者在es5没有name属性,es6的时候,这种函数表达式才有name属性。函数定义后,其他属性,两者都有,比如length,arguments。
那么,如何定义箭头函数呢
如下:
const speak = ()=>{}
那么,箭头函数相比之前传统函数不同有如下:
1.箭头函数没有构造函数,不能使用new 创建对象。
如图:
2.箭头函数,函数体内的this对象就是定义的时候所在的对象。而不是使用时所在的对象。
3.箭头函数没有arguments属性。所以在该arguments对象不可以在函数体内部使用。如果需要用到这类效果,可以结合rest使用。
4.不可以使用yield命令。因此箭头函数不能用作Generator函数。
箭头函数的使用场景
箭头函数对于this的指向,使得对象内部定义方法很友好。
var handle = {
id:"123456",
init: function(){
document.addEventListener('click',event=>this.doSomething(event.type),false)
},
doSomething(type){
console.log('Handle '+type+' for '+this.id)
}
}
截图如下:
如果使用匿名函数声明事情处理函数,在调用完监听方法(init)后,点击document,如图,会报出一个错误。因为document没有这个doSomething方法
对象属性的简洁表达式
es6允许直接写入变量和函数作为对象的属性和方法
var foo = 'bar'
function speak(content){
console.log(content);
return{ content }//相当于{content:content}
}
var obj = {
foo,//相当于{foo:foo}
speak(content){
console.log(content);
return{ content }
}
}
1.对象属性和值,同名可简写,简写如上面 obj.foo。
2.对象方法可简写,简写如上面 obj.speak 。等同于下面
var o = {
speak: function(content){...}
}
所以总体来说,这种写法会非常方便。
在CommonJS模块输出也很方便。
例如:module.exports = {getItem,setItem,clear}
// 等同于
module.exports = { getItem: getItem, setItem: setItem, clear: clear }
Symbol
Symbol是ES6后出现的新的原始数据类型。表示独一无二的值。
Symbol值是通过Symbol函数生成的。
如图:
Symbol函数生成的值不管内部字符串有无定义,定义相同字符串,生成后的值都不相同。如下代码
var emum1 = Symbol();
var emum2 = Symbol();
var firstResult = emum2 == emum1;
var emum3 = Symbol("exsit value");
var emum4 = Symbol("exsit value");
var secondResult = emum3 == emum4;
console.log("firstResult...",firstResult," secondResult...",secondResult);
// execpted output: firstResult... false secondResult... false
结果如图
所以Symbol值是独一无二的,即使Symbol函数使用相同字符串生成的Symbol值。
因此有如下实例。
实例:消除魔术字符串
魔术字符串指的是,在代码之中多次出现、与代码形成强耦合的某个具体字符串或值。风格良好的代码,应该尽量消除魔术字符串。而由含义清晰的变量代替。
function getArea(shape,options){
var area = 0;
switch(shape){
case 'Triangle':// 魔术字符串
area= 5*options.width * options.height;
break;
// more code ...
}
return area;
}
grtArea('Triangle', {width: 100, height: 100 });// 魔术字符串。
上面代码的“Triangle”就是一个魔术字符串。我们可以消除它。如下
// 常用的一种
var shanpeType = {
triangle: 'Triangle'
}
function getArea(shape,options){
var area = 0;
switch(shape){
case shanpeType.triangle:// 魔术字符串
area= 5*options.width * options.height;
break;
// more code ...
}
return area;
}
grtArea(shanpeType.triangle, {width: 100, height: 100 });// 魔术字符串。
// 使用Symbol值的一种。
// 仔细分析后,shanpeType.triangle的值具体是什么不重要。所以可以使用Symbol值代替
const shanpeType = {
triangle: Symbol()
}
function getArea(shape,options){
var area = 0;
switch(shape){
case shanpeType.triangle:// 魔术字符串
area= 5*options.width * options.height;
break;
// more code ...
}
return area;
}
grtArea(shanpeType.triangle, {width: 100, height: 100 });// 魔术字符串。
部分内置方法(Symbol.hasInstance,Symbol.isConcatSpreadable)
Symbol.hasInstance
对象使用instanceof会调用这个方法,判断该对象是否为某个构造函数的实例,比如foo instanceof Foo,实际上,调用的是Foo[Symbol.hasInstance] ()
class MyClass{
[Symbol.hasInstance](foo){
return foo instanceof Array;
}
}
[1,2,3] instanceof new MyClass
// excepted output true
对象的Symbol.hasInstance 属性指向一个内部方法,
new MyClass() 会返回一个实例。
该实例的Symbol.hasInstance方法会在进行instanceof运算时自动调用。
Symbol.isConcatSpreadable
该属性等于一个布尔值,表示该对象用Array.prototype.concat()时是否可以展开数组。
let arr1 = ['c','d'];
['a','b'].concat(arr1,'e');
// excpted outpout ["a", "b", "c", "d", "e"]
arr1[Symbol.isConcatSpreadable];
// excpted outpout undefined
let arr2 = ['c','d'];
arr2[Symbol.isConcatSpreadable] = false;
['a','b'].concat(arr2,'e');
// excpted outpout ["a", "b", ["c", "d"], "e"]
arr2[Symbol.isConcatSpreadable]
// excpted outpout false
数组对该属性undefined或者true,比如arr1[Symbol.isConcatSpreadable]为赋值时候,是undefined,这个时候,数组调用concat方法,arr1的默认行为是可以展开的,所以都有上面第一种的效果。
为false的时候,就是第二种的效果,这时arr2是数组[Symbol.isConcatSpreadable] = false时候的效果。
类数组也可以展开
let obj = {length:2, 0:'c',1:'d'};
['a','b'].concat(obj,'e');
// excpted outpout ["a", "b", {…}, "e"]
obj[Symbol.isConcatSpreadable]= true;
['a','b'].concat(obj,'e');
// excpted outpout ["a", "b", "c", "d", "e"]
对于新类而言,Symbol.isConcatSpreadable属性必须类的this实例属性
class A1 extends Array{
constructor(args){
super(args);
this[Symbol.isConcatSpreadable] = true;
}
}
class A2 extends Array{
constructor(args){
super(args);
this[Symbol.isConcatSpreadable] = false;
}
}
let a1 = new A1()
a1[0] = 3;
a1[1] = 4;
let a2 = new A2()
a2[0] = 5;
a2[1] = 6;
[1,2].concat(a1).concat(a2)
// excepted output [1, 2, 3, 4, [5, 6]]
上面代码类A1是可扩展的,类A2是不可扩展的。
代码例子,部分借鉴《ES6标准入门》,阮一峰注写。