html中箭头函数有什么意义呀,什么是ES6箭头函数?与普通函数主要区别在哪里?到底该不该使用箭头函数?...

箭头函数是匿名函数,ES5匿名函数的语法糖;但又增加了ES5所没有的一些优点,接下来我们一起来看一看箭头函数

// ES5

vat tt = function tt() {

return 55 + 99;

}

// ES6

vat tt = () => 55 + 99

// 是不是一对比,写法的差异就看出来了

ES6增加了箭头函数:

let func = value => value;

// 相当于

let func = function () {

return value;

}

// 如果需要给函数传入多个参数:

let func = (value, num) => value * num;

// 如果函数的代码块需要多条语句:

let func = (value, num) => {

return value * num;

}

// 如果需要直接返回一个对象:

let func = (value, num) => ({total: value * num});

// 与变量解构结合

let func = ({value, num}) => ({total: value * num})

// 使用

var result = func({

value: 10,

num: 10

})

console.log(result); // {total: 100}

以上是箭头函数的用法,了解了箭头函数的用法之后呢,我们一起来进一步的看一看箭头函数,到底和我们的普通函数有什么区别,好处在哪?

1.没有this

箭头函数没有this,所以需要通过查找作用域链来确定this的值。

这就意味着如果箭头函数被非箭头函数包含,this绑定的就是最近一层非箭头函数的this。

模拟一个实际开发中的例子:

我们的需求是点击一个按钮,改变该按钮的背景色。

为了方便开发,我们抽离一个Button组件,当需要使用的时候直接:传入元素id值即可绑定该元素点击时改变背景色的事件

new Button('button');

// HTML代码如下:

点击变色

// javascript代码:

function Button(id) {

this.element = document.querySelector('#' + id);

this.bindEvent();

}

Button.prototype.bindEvent = function() {

this.element.addEventListener("click", this.setBgColor, false);

}

Button.prototype.setBgColor = function() {

this.element.style.backgroundColor = '#abcdef';

}

vat button = new Button('button');

看着好像没有问题,结果却是报错 Uncaught TypeError: Cannot read property 'style' of undefined

这是因为当使用addEventListener() 为一个元素注册事件的时候,事件函数里的this值是该元素的引用。

所以如果我们在setBgColor中console.log(this), this指向的是按钮元素,那this.element就是undefined, 报错自然就理所当然了。

也许你会问,既然this都指向了按钮元素,那我们直接修改setBgColor函数为:

Button.prototype.setBgColor = function() {

this.style.backgroundColor = '#abcdef';

}

不就可以解决这个问题了?

确实可以这样做,但是在实际开发中,我们可能会在setBgColor中还调用其他的函数,比如写成这样:

Button.prototype.setBgColor = function() {

this.setElementColor();

this.setOtherElementColor();

}

所以我们还是希望setBgColor中的this是指向实例对象的,这样就可以调用其他的函数。

利用ES5,我们一般会这样做:

Button.prototype.bindEvent = function() {

this.element.addEventListener("click", this.setBgColor.bind(this), false);

}

为避免addEventListener的影响,使用bind强制绑定setBgColor()的this为实例对象

使用ES6,我们可以更好的解决这个问题:

Button.prototype.bindEvent = function() {

this.element.addEventListener("click", event => this.setBgColor(event), false);

}

由于箭头函数没有this,所以会向外层查找this的值,即bindEvent中的this,此时this指向实例对象,所以可以正确的调用this.setBgColor方法,而this.setBgColor中的this也会正确指向实例对象。

在这里再额外提一点,就是注意bindEvent和setBgColor在这里使用的是普通函数的形式,而非箭头函数,如果我们改成箭头函数,会导致函数里的this指向window对象(非严格模式下)。

最后,因为箭头函数没有this,所以也不能用call()、apply()、bind()这些方法改变this的指向,可以看一个例子:

var value = 1;

var result = (() => this.value).bind({value: 2})();

console.log(result); // 1

2.没有arguments

箭头函数没有自己的arguments对象,这不一定是件坏事,因为箭头函数可以访问外围函数的arguments对象:

function constant() {

return () => arguments[0];

}

var result = constant(1);

console.log(result()); // 1

那如果我们就是要访问箭头函数的参数呢?

你可以通过命名参数或者rest参数的形式访问参数:

let nums = (...nums) => nums;

3.不能通过new关键字调用

Javascript函数有两个内部方法:[[Call]]和[[Construct]]。

当通过new调用函数时,执行[[Construct]]方法,创建一个实例对象,然后再执行函数体,将this绑定到实例上。

当直接调用的时候,执行[[Call]]方法,直接执行函数体。

箭头函数并没有[[Construct]]方法,不能被用作构造函数,如果通过new的方式调用,会报错。

var Foo = () => {};

var foo = new Foo(); // TypeError: Foo is not a constructor

4.没有原型

由于不能使用new调用箭头函数,所以也没有构建原型的需求,于是箭头函数也不存在prototype这个属性。

5.没有super

连原型都没有,自然也不能通过super来访问原型的属性,所以箭头函数也没有super的,不过跟this、arguments一样,这些值由外围最近一层非箭头函数决定。

在出现了箭头函数之后是不是就可以舍弃原来的普通函数了呢?答案一定是否定的,一些情况下我们最好不要去进行箭头函数的操作,那都有哪些情况呢?

(1) 在对象上定义函数

先来看下面这段代码

var obj = {

array: [1, 2, 3],

sum: () => {

console.log(this === window); // => true

return this.array.reduce((result, item) => result + item);

}

}

obj.sum();

// Throws "TypeError: Cannot read property 'reduce' of undefined"

sum方法定义在obj对象上,当调用的时候我们发现抛出了一个TypeError,因为函数中的this是window对象,所以this.array也是undefined。原因也很简单,相信只要了解es6 箭头函数的都知道

箭头函数没有它自己的this值,箭头函数内的this值继承自外围作用域

解决方法也很简单,就是不用呗。这里可以用es6里函数表达式的简洁语法,在这种情况下,this值就取决于函数的调用方式了。

var obj = {

array: [1, 2, 3],

sum() {

console.log(this === obj); // => true

return this.array.reduce((result, item) => result + item);

}

}

obj.sum(); // => 6

通过object.method()语法调用的方法使用非箭头函数定义,这些函数需要从调用者的作用域中获取一个有意思的this值。

(2)在原型上定义函数

在对象原型上定义函数也是遵循着一样的规则

function Person(pName) {

this.pName = pName;

}

Person.prototype.sayName = () => {

console.log(this === window); // => true

return this.pName;

}

var person = new Person('zhangSan');

person.sayName(); // => undefined

// 使用function函数表达式

function Person(pName) {

this.pName = pName;

}

Person.prototype.sayName = function() {

console.log(this === person); // => true

return this.pName;

}

var person = new Person('zhangSan');

person.sayName(); // => zhangSan

(3)动态上下文中的回调函数

this是js中非常强大的特点,他让函数可以根据其调用方式动态的改变上下文,然后箭头函数直接在声明时就绑定了this对象,所以不再是动态的。

在客户端,在dom元素上绑定事件监听函数是非常普遍的行为,在dom事件被触发时,回调函数中的this指向该dom,可当我们使用箭头函数时:

var button = document.getElementById('myButton');

button.addEventListener('click', () => {

console.log(this === window); // => true

this.innerHTML = 'clicked button';

})

因为这个回调的箭头函数是在全局上下文中被定义的,所以他的this是window。所以当this是由目标对象决定时,我们应该使用函数表达式:

var button = document.getElementById('myButton');

button.addEventListener('click', function() {

console.log(this === button); // => true

this.innerHTML = 'clicked button';

})

(4)构造函数中

在构造函数中,this指向新创建的对象实例

this instanceOf MyFunction === true

需要注意的是,构造函数不能使用箭头函数,如果这样做会抛出异常

var Person = (name) => {

this.name = name;

}

var person = new Person('zhangSan');

// Uncaught TypeError: Person is not a constructor

理论上来说也是不能这么做的,因为箭头函数在创建时this对象就绑定了,更不会指向对象实例。

(5)太简短的函数

箭头函数可以让语句写的非常的简洁,但是一个真实的项目,一般由多个开发者共同协作完成,就算由单人完成,后期也并不一定是同一个人维护,箭头函数有时候并不会让人很好的理解,比如

let multiply = (a, b) => b === undefined ? b => a * b : a * b;

let double = multiply(2);

double(3); // => 6

multiply(2,3); // => 6

这个函数的作用就是当只有一个参数a时,返回接受一个参数b返回a * b的函数,接受两个参数时直接返回乘积,这个函数可以很好的工作并且看起来很简洁,但是从第一眼看去并不是很好理解。为了让这个函数更好的让人理解,我们可以为这个箭头函数加一对花括号,并加上return语句买或者直接使用函数表达式:

function multiply(a, b) {

if (b === undefined) {

return function (b) {

return a * b;

}

}

return a * b;

}

let double = multiplu(2);

double(3); // => 6;

multiply(2, 3); // => 6

总结

最后,关于箭头函数,引用MDN的介绍就是:箭头函数表达式的语法比函数表达式更短,并且不绑定自己的this,arguments,super。

毫无疑问,箭头函数带来了很多便利。恰当的使用箭头函数可以让我们避免使用早起的.bind()函数或者需要固定上下文的地方并且让代码更加简洁。

箭头函数也有一些不便利的地方。我们在需要动态上下文的地方不能使用箭头函数:定义需要动态上下文的函数,构造函数,需要this对象作为目标的回调函数以及用箭头函数难以理解的语句。在其他情况下,请尽情使用箭头函数。

你可能感兴趣的