es6部分新特性(箭头函数,对象属性的简洁表达式,Symbol)

428 阅读4分钟

es6部分新特性(箭头函数,对象属性的简洁表达式,Symbol)

箭头函数

传统函数

传统函数有两种表达方式,一种是函数声明,另一种是函数表达式。

函数声明格式如下:

function Person(){}

函数表达式格式如下:

const Person = function (){}

这两种示例的函数都有构造函数,前者有name属性。后者在es5没有name属性,es6的时候,这种函数表达式才有name属性。函数定义后,其他属性,两者都有,比如length,arguments。

那么,如何定义箭头函数呢

如下:

const speak = ()=>{}

那么,箭头函数相比之前传统函数不同有如下:

1.箭头函数没有构造函数,不能使用new 创建对象。

如图:

image-20200829090457944.png

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)
    }
}

截图如下:

image-20200829091847949

如果使用匿名函数声明事情处理函数,在调用完监听方法(init)后,点击document,如图,会报出一个错误。因为document没有这个doSomething方法

image-20200829092130624

对象属性的简洁表达式

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标准入门》,阮一峰注写。