[原创] 码路工人

大家好,这里是码路工人有力量,我是码路工人,你们是力量。


如果没用过CSharp的lambda 表达式,也没有了解过ES6,那第一眼看到这样代码什么感觉?

/* eg.0
* function definition
*/ var arr = [1,2,3,5,8,13,21] arr.forEach(n => console.log(n))

数组的forEach 方法里需要传入一个函数(没用过 CSharp 里委托 delegate 的也许会觉得奇怪,js 里参数竟然可以是一个方法,其实 C# 里也是早就有的),这n =>是什么鬼?

这是今天要说的主角,箭头函数Arrow Function

#注:

  • C# 中操作集合的各种 lambda 表达式其实就是一个个简短的匿名函数,
  • ES6的箭头函数就可以理解为 C# 中的 lambda 表达式式的东西,
  • Python 中同样也是有 lambda 表达式的(当时用的时候有限定,只能写一句),
  • 只是不同语言间写法或语法不同,所以我有个观点就是:
  • 认真学一门语言,不只停留在入门,不能说精通也要达到进阶,
  • 再去学其它的,就会发现编程语言是相通的,编程思想更是相通的
  • 码工我不是搞 Java 的,但是会 C# 的看起 Java 代码也是不太费劲,因为真的很像

    => Java 里也有 lambda 。

1. Arrow Function 的基本用法

1.1 本质就是匿名函数

  普通定义一个函数,要用到function 关键字,不管是存在提升现象的function foo() { } 还是定义给变量var foo = function() { } ,这样的话调用时才能找到这个函数,就像每个人都有名字一样。

  匿名函数就不一样了,它没有名字,因此只能在定义它的位置调用(这么说不严谨,但不影响理解,具体见下文)。所以,用箭头函数去定义一个单独函数而不调用不执行,是没有意义的。当然能这么写,js本身不会报错。

  除了定义时的区别,匿名函数使用时,跟普通函数还是相似的,要么定义给一个变量,要么直接当作回调函数写在参数位置。

  因为本身就没有function 关键字和方法名,也就无法像ES5里那样定义类/构造函数。不可能也没理由这样用。如果 "var Foo = () => { }" 这样写,也不能当作类/构造函数,"new Foo()" 的时候会报错。毕竟用ES6的话也不会这样定义类。(用classconstructor

/* eg.1
* function definition
*/ //------------------------------------------------- function logParam(param) {
console.log(param)
} logParam("foo") // foo //------------------------------------------------- // Should not define a funtion using arrow-function itself
// because no function name to call and will not execute
(param) => console.log(param) const foo = (param) => console.log(param)
foo("bar") // bar //-------------------------------------------------

1.2 基本使用特点

  • 普通的正常写法

    /* eg.2
    * arrow function
    */ //-------------------------------------------------
    var arr = [1,2,3,5,8,13,21] // Normal:
    console.log(arr.map(function(item, index) {
    return `No.${index}: ${item}`
    }))
    //["No.0: 1", "No.1: 2", "No.2: 3", "No.3: 5", "No.4: 8", "No.5: 13", "No.6: 21"] // Use arrow function:
    console.log(arr.map((item, index) => {
    return `No.${index}: ${item}`
    }))
    //["No.0: 1", "No.1: 2", "No.2: 3", "No.3: 5", "No.4: 8", "No.5: 13", "No.6: 21"]
    //-------------------------------------------------

    最直观的一点就是写法上稍微简易了一丢丢。它基本的特点就是简易了,继续往下看。

  • 只有一个参数时,参数括号 可省略

    /* eg.2
    * arrow function
    */ //-------------------------------------------------
    var arr = [1,2,3,5,8,13,21] // Normal:
    arr.forEach(function(item) {
    console.log("当前元素:" + item)
    }) // Use arrow function:
    arr.forEach( item => {
    console.log("当前元素:" + item)
    })
    //-------------------------------------------------

    以上例子中只有一个item参数,所以参数括号省略了也能正常执行。

  • 方法体只有一句 { return expression } 时,花括号跟 return 可省略

    当然,如果本身就没有做return也是可以只省略花括号的,没有返回值处理时默认就是返回undefined

    /* eg.3
    * arrow function
    */
    //------------------------------------------------- var arr = [1,2,3,5,8,13,21] // Normal:
    arr.forEach(function(item){
    console.log("当前元素:" + item)
    })
    console.log(arr.map(function(item,index){
    return `No.${index}: ${item}`
    })) // Use arrow function:
    arr.foreach((item,index) => console.log(`No.${index}: ${item}`))
    console.log(arr.map((item,index) => `No.${index}: ${item}` )) //-------------------------------------------------

    以上例子中分别演示了无return与有return时箭头函数中的简便写法。

    执行结果可以在 chrome 浏览器下的 console 里查看(F12打开开发者模式)。

1.3 补充:没有参数时

  没有参数的情况也是有的,可以跟普通函数一样,空括号就可以了。另外,还有一种约定俗成的写法:_ 。如下:

/* eg.4
* arrow function: no-param
*/ //-------------------------------------------------
const foo = () => "bar"
const foo = _ => "bar" // as same as ↓
const foo = function () {
return "bar"
}

2. 其它特点

2.1 this 指向的问题

  箭头函数用起来感觉轻便了许多,但也有不少问题。其中主要、最经常遇到的可能就是this指向问题了。

/* eg.5
* arrow function: this
*/
//------------------------------------------------- const person = {
name: "Coder Power",
greet1: function() {
console.log(this)
console.log("Hello!I am " + this.name + ".")
},
greet2: () => {
console.log(this)
console.log("Hello!I am " + this.name + ".")
}
} // 'this' in normal function
// is object person
person.greet1() // 'this' in arrow function
// is object window
person.greet2() //-------------------------------------------------

  以上代码例子中,greet1this指向为person对象。这一点非常好理解,以外 js 中的 this 是谁调用,指向谁。

  而greet2中的this却指向了 window对象。怎么会这样?

  其实码工刚开始也没弄明白,只是知道 this 不一样。后来仔细想了想,箭头函数里的 this 为定义函数时它外部函数里的 this ,也就时在 person 定义中,这时的 this 就是 window。(window.person)

  • 箭头函数this总结

    => 函数没有自己的this

    => 函数里的this 是父级作用域里的this

    => 函数不能通过apply/call 的方式绑定this

    /* eg.6
    * arrow function: this
    */
    //------------------------------------------------- // can not change 'this' in arrow function
    // by apply/call
    person.greet2.call(person)
    person.greet2.apply(person)
    // ↑"this.name" will still be undefined
    //-------------------------------------------------

    所以在需要用到this 的方法中要慎重。

2.2 ES6箭头函数的其它特点

  在前文 1.1 中我们就说了,箭头函数定义出来的函数变量不能通过new 来实例化出一个对象。

它跟继承扯不上关系,不能做构造函数,也没有原型(prototype)。获取参数也仅限与方法调用传参,不能用arguments来取。

ES6箭头函数中没有以下属性/对象:

  • 箭头函数不能new

  • 箭头函数没有prototype

  • 箭头函数没有super

    上一篇中介绍了 ES5 及 ES6 里的类与继承,其中 ES6 里子类的构造函数里必须先调用一次super 也就是父类的构造函数,才生成了实例对象this 。而箭头函数是没有super 的。

  • 箭头函数没有arguments

  • 箭头函数没有new.target (本来就不能 new ,就更没有 new.target 了)

    上述这些相对不常用或说在使用箭头函数时相关性较小,箭头函数本意是简化书写,更多的是用在填写一个普通的回调函数上。


读到这里,对于 JavaScript/ES6 里箭头函数 Arrow Function 的使用方法就掌握差不多了吧。

思考一下,哪些场景下适合/不适合用箭头函数呢?可以评论区留个言再走啊~

希望对你能有帮助,下篇再见。


欢迎关注分享,一起学习提高吧。

QRCode/微信订阅号二维码


[ES6系列-02]Arrow Function:Whats this?(箭头函数及它的this及其它)的更多相关文章

  1. ES6躬行记(15)——箭头函数和尾调用优化

    一.箭头函数 箭头函数(Arrow Function)是ES6提供的一个很实用的新功能,与普通函数相比,不但在语法上更为简洁,而且在使用时也有更多注意点,下面列出了其中的三点: (1)由于不能作为构造 ...

  2. ES6学习总结一(变量;箭头函数;解构赋值)

    一.变量 var  1 可以重复声明(var a=1;var a=7;)(一开始用着会觉得限制很少,但是在大型项目会麻烦,人多嘴杂的时候定义重复了就容易出问题还不好找) 2 无法限制修改 3 没有块级 ...

  3. es6笔记 day2---函数默认参数、箭头函数、剩余参数

    函数变化: 1.函数默认参数 2.函数参数默认是已经定义了,不能再使用let.const声明 3.扩展运算符.rest运算符 ...就是扩展运算符,它的作用就是把数组给展开 结合函数使用传参,也可以将 ...

  4. [ES6系列-07]Generator Function: 生成器函数

    [原创]码路工人 Coder-Power 大家好,这里是码路工人有力量,我是码路工人,你们是力量. github-pages 博客园cnblogs Generator function 生成器函数是E ...

  5. ES6系列之箭头函数

    本系列是在平时阅读.学习.实际项目中有关于es6中的新特性.用发的简单总结,目的是记录以备日后温习:本系列预计包含let/const.箭头函数.解构.常用新增方法.Symbol.Set&Map ...

  6. [译]ES6箭头函数和它的作用域

    原文来自我的前端博客: http://www.hacke2.cn/arrow-functions-and-their-scope/ 在ES6很多很棒的新特性中, 箭头函数 (或者大箭头函数)就是其中值 ...

  7. ES6箭头函数和它的作用域

    原文来自我的前端博客: http://www.hacke2.cn/arrow-functions-and-their-scope/ http://es6rocks.com/2014/10/arrow- ...

  8. ES6系列之解构

    本系列是在平时阅读.学习.实际项目中有关于es6中的新特性.用发的简单总结,目的是记录以备日后温习:本系列预计包含let/const.箭头函数.解构.常用新增方法.Symbol.Set&Map ...

  9. ES6系列之let/const及块级作用域

    本系列是在平时阅读.学习.实际项目中有关于es6中的新特性.用发的简单总结,目的是记录以备日后温习:本系列预计包含let/const.箭头函数.解构.常用新增方法.Symbol.Set&Map ...

随机推荐

  1. 算法竞赛进阶指南--hamilton路径

    // hamilton路径 int f[1 << 20][20]; int hamilton(int n, int weight[20][20]) { memset(f, 0x3f, si ...

  2. muduo网络库源码学习————线程特定数据

    muduo库线程特定数据源码文件为ThreadLocal.h //线程本地存储 // Use of this source code is governed by a BSD-style licens ...

  3. JS中由闭包引发内存泄露的深思

    目录 一个存在内存泄露的闭包实例 什么是内存泄露 JS的垃圾回收机制 什么是闭包 什么原因导致了内存泄露 参考 1.一个存在内存泄露的闭包实例 var theThing = null; var rep ...

  4. 面试官:你说你懂i++跟++i的区别,那你会做下面这道题吗?

    面试官:你说你懂i++跟++i的区别,那你知道下面这段代码的运行结果吗? 面试官:"说一说i++跟++i的区别" 我:"i++是先把i的值拿出来使用,然后再对i+1,++ ...

  5. mysql优化–explain分析sql语句执行效率

    Explain命令在解决数据库性能上是第一推荐使用命令,大部分的性能问题可以通过此命令来简单的解决,Explain可以用来查看SQL语句的执行效 果,可以帮助选择更好的索引和优化查询语句,写出更好的优 ...

  6. 认识mysql3个基本库

    一.3个基本库 数据库初始化安装完毕会有三个基本库mysql .information_schema.performace_schema.作为应用程序开发者,平时较少关注这些数据库尤其是后两者.但是通 ...

  7. 201771010113 李婷华 《面向对象程序设计(Java)》第十一周总结

    一.理论知识部分 第九章  集合 1.数据结构介绍: 线性结构:线性表,栈,队列,串,数组,文件.非线性结构:树,图. 散列表:又称为哈希表. 散列表算法的基本思想是:以结点的关键字为自变量,通过一定 ...

  8. STM32 TIM高级定时器死区时间的计算

    STM32 TIM高级定时器的互补PWM支持插入死区时间,本文将介绍如何计算以及配置正确的死区时间. 文章目录 什么是死区时间? 数据手册的参数 如何计算合理的死区时间? STM32中配置死区时间 什 ...

  9. Linux文件操作命令并举例说明其作用

    ls ,常用于查看当前文件下有工作中需要的文件 cd, 常用于进行切换文件的位置 vim,常用于编辑软件系统相关的配置文件 ps –ef|grep jdk,常用语显示跟jdk有关的进程   |:表示 ...

  10. 【原理探究】女朋友问我ArrayList遍历时删除元素的正确姿势是什么?

    简介 我们在项目开发过程中,经常会有需求需要删除ArrayList中的某个元素,而使用不正确的删除方式,就有可能抛出异常.或者在面试中,会遇到面试官询问遍历时如何正常删除元素.所以在本篇文章中,我们会 ...