整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

JavaScript 箭头函数特点与用法详解

家好,很高兴又见面了,我是姜茶的编程笔记,我们一起学习前端相关领域技术,共同进步,也欢迎大家关注、点赞、收藏、转发,您的支持是我不断创作的动力

我们来聊聊箭头函数(就是下面这个东西)!箭头函数的语法比传统的函数表达式更简洁,而且它们没有自己的 thisargumentssupernew.target。它们非常适合用在需要匿名函数的地方,同时不能作为构造函数使用。

// 当只有一个参数时,圆括号不是必须的
(singleParam) => { statements }
singleParam => { statements }

// 没有参数的函数必须加圆括号
() => { statements }

箭头函数有两个主要优点:

1️⃣ 语法更简洁

2️⃣ 不会绑定 this

切入正题【特点】

没有自己的 this

箭头函数不会创建自己的 this,它只会继承外层作用域的 this

function Person() {
 this.age = 0;

 setInterval(() => {
  // this 正确地指向 p 实例
  console.log(this === p); // true
  this.age++;
 }, 1000);
}

var p = new Person();

与严格模式的关系

由于 this 是词法绑定的,严格模式中与 this 相关的规则将被忽略。

var f = () => { 'use strict'; return this; };
f() === window; // 或 global

通过 call、apply 或 bind 调用

因为箭头函数没有自己的 this,使用这些方法调用时只能传递参数,它们的第一个参数 this 会被忽略。

let adder = {
 base: 1,
 add: function (a) {
  console.log(this === adder); // true
  let f = (v) => v + this.base;
  return f(a);
 },
 addThruCall: function (a) {
  let f = (v) => {
   console.log(this === adder); // true
   console.log(`v 的值是 ${v},this.base 的值是 ${this.base}`); // 'v 的值是 1,this.base 的值是 1'
   return v + this.base;
  };
  let b = { base: 3 };
  // call() 方法不能绑定 this 为 b 对象,第一个参数 b 被忽略了
  return f.call(b, a);
 }
};

console.log(adder.add(1)); // 输出 2
console.log(adder.addThruCall(1)); // 输出 2

使用箭头函数作为方法

箭头函数没有 this 绑定。

"use strict";
var obj = {
 i: 10,
 b: () => console.log(this.i, this), // undefined, Window{...}
 c: function () {
  console.log(this.i, this); // 10, Object {...}
 }
};
obj.b();
obj.c();

使用 new 操作符

箭头函数不能用作构造函数,用 new 调用会抛出错误。

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

作为匿名函数

ES6 的箭头函数表达式是匿名函数的一种简写方式:

// 匿名函数
let show = function () {
    console.log("匿名函数")
};
show(); // "匿名函数"

let show1 = () => console.log("匿名函数");
show1(); // "匿名函数"

不过,箭头函数和传统匿名函数在实际操作中还是有一些区别的。

最后

如果你有任何问题或建议,欢迎在评论区留言交流!祝你编程愉快!

建函数还有另外一种非常简单的语法,并且这种方法通常比函数表达式更好。

它被称为“箭头函数”,因为它看起来像这样:

let func = (arg1, arg2, ..., argN) => expression;

这里创建了一个函数 func,它接受参数 arg1..argN,然后使用参数对右侧的 expression 求值并返回其结果。

换句话说,它是下面这段代码的更短的版本:

let func = function(arg1, arg2, ..., argN) {
  return expression;
};

让我们来看一个具体的例子:

let sum = (a, b) => a + b;

/* 这个箭头函数是下面这个函数的更短的版本:

let sum = function(a, b) {
  return a + b;
};
*/

alert( sum(1, 2) ); // 3

可以看到 (a, b) => a + b 表示一个函数接受两个名为 a 和 b 的参数。在执行时,它将对表达式 a + b 求值,并返回计算结果。

  • 如果我们只有一个参数,还可以省略掉参数外的圆括号,使代码更短。
  • 例如:
  • let double = n => n * 2; // 差不多等同于:let double = function(n) { return n * 2 } alert( double(3) ); // 6
  • 如果没有参数,括号将是空的(但括号应该保留):
  • let sayHi = () => alert("Hello!"); sayHi();

箭头函数可以像函数表达式一样使用。

例如,动态创建一个函数:

let age = prompt("What is your age?", 18);

let welcome = (age < 18) ?
  () => alert('Hello') :
  () => alert("Greetings!");

welcome();

一开始,箭头函数可能看起来并不熟悉,也不容易读懂,但一旦我们看习惯了之后,这种情况很快就会改变。

箭头函数对于简单的单行行为(action)来说非常方便,尤其是当我们懒得打太多字的时候。

多行的箭头函数

上面的例子从 => 的左侧获取参数,然后使用参数计算右侧表达式的值。

但有时我们需要更复杂一点的东西,比如多行的表达式或语句。这也是可以做到的,但是我们应该用花括号括起来。然后使用一个普通的 return 将需要返回的值进行返回。

就像这样:

let sum = (a, b) => {  // 花括号表示开始一个多行函数
  let result = a + b;
  return result; // 如果我们使用了花括号,那么我们需要一个显式的 “return”
};

alert( sum(1, 2) ); // 3

更多内容

在这里,我们赞扬了箭头函数的简洁性。但还不止这些!

箭头函数还有其他有趣的特性。

为了更深入地学习它们,我们首先需要了解一些 JavaScript 其他方面的知识,因此我们将在后面的 深入理解箭头函数 一章中再继续研究箭头函数。

现在,我们已经可以用箭头函数进行单行行为和回调了。

总结

对于一行代码的函数来说,箭头函数是相当方便的。它具体有两种:

  1. 不带花括号:(...args) => expression — 右侧是一个表达式:函数计算表达式并返回其结果。
  2. 带花括号:(...args) => { body } — 花括号允许我们在函数中编写多个语句,但是我们需要显式地 return 来返回一些内容。

任务

用箭头函数重写

用箭头函数重写下面的函数表达式:

function ask(question, yes, no) {
  if (confirm(question)) yes();
  else no();
}

ask(
  "Do you agree?",
  function() { alert("You agreed."); },
  function() { alert("You canceled the execution."); }
);

解决方案

function ask(question, yes, no) {
  if (confirm(question)) yes();
  else no();
}

ask(
  "Do you agree?",
  () => alert("You agreed."),
  () => alert("You canceled the execution.")
);

是不是看起来精简多了?

头函数(Arrow Function)是ES6新增的特性,在网上看了一篇个人博客的讲解,写的例子里面居然还有声明的变量没有被使用,却还在招揽学生做IT培训,真的误人子弟。

一个简单的例子

为了说明箭头函数,我们先写个简单的代码:

const domain_list = [
  'www.abot.cn',
  'www.tseo.cn',
  'www.weiduke.com',
  'yanyubao.tseo.cn'
];

console.log(domain_list.map(domain_item => domain_item.length));
// expected output: Array [11, 11, 15, 16]

关于JavaScript中map函数的使用,这里不赘述,不懂的抓紧恶补。

重点看第8行。

domain_item => domain_item.length

等价于以下写法:

function(domain_item) {return domain_item.length}

所以以上代码的ES5的写法为:

const domain_list = [
  'www.abot.cn',
  'www.tseo.cn',
  'www.weiduke.com',
  'yanyubao.tseo.cn'
];

console.log(domain_list.map(function(domain_item) {
	return domain_item.length;
}));
// expected output: Array [11, 11, 15, 16]

箭头函数基本语法

总结总结一下,ES6的基本语法

(param1, param2, …, paramN) => { statements }

(param1, param2, …, paramN) => expression

//相当于:(param1, param2, …, paramN) =>{ return expression; }

// 当只有一个参数时,圆括号是可选的:

(singleParam) => { statements }

singleParam => { statements }

// 没有参数的函数应该写成一对圆括号。

() => { statements }

对照以上的例子,什么是箭头函数应该一目了然了。

箭头函数没有单独的this值

this一般是这样被定义的:

  • 如果是该函数是一个对象的方法,则它的this指针指向这个对象
  • 在严格模式下的函数调用下,this指向undefined
  • 如果是该函数是一个构造函数,this指针指向一个新的对象

this的弊端

function Person() {
  // Person() 构造函数定义 `this`作为它自己的实例.
  this.age = 0;

  setInterval(function growUp() {
    // 在非严格模式, growUp()函数定义 `this`作为全局对象,
    // 与在 Person()构造函数中定义的 `this`并不相同.
    this.age++;
  }, 1000);
}

var p = new Person();

在ECMAScript 3/5中,通过将this值分配给封闭的变量,可以解决this问题。

function Person() {
  var that = this;
  that.age = 0;

  setInterval(function growUp() {
    // 回调引用的是`that`变量, 其值是预期的对象.
    that.age++;
  }, 1000);
} 

或者,可以创建绑定函数,以便将预先分配的this值传递到绑定的目标函数(上述示例中的growUp()函数)。

箭头函数的解决方案

箭头函数不会创建自己的this,它只会从自己的作用域链的上一层继承this。因此,在下面的代码中,传递给setInterval的函数内的this与封闭函数中的this值相同:

function Person(){
  this.age = 0;

  setInterval(() => {
    this.age++; // |this| 正确地指向 p 实例
  }, 1000);
}

var p = new Person();

如果不理解以上代码,那么再强调一遍:因为箭头函数没有this,所以setInterval函数中的箭头函数的this,只能是他的上一级函数的this。如果说到这样还不理解,建议恶补语文。

高级语法和进阶

箭头函数的进阶知识,包括:

  • 1、高级语言规则
  • 2、严格模式下的使用
  • 3、call和apply的调用

感兴趣的小伙伴可以自个去研究。