JavaScript中的普通函数和箭头函数的区别和用法详解

最近被问到了一个问题:

javaScript 中的箭头函数 ( => ) 和普通函数 ( function ) 有什么区别?

我当时想的就是:这个问题很简单啊~(flag),然后做出了错误的回答……

箭头函数中的 this 和调用时的上下文无关,而是取决于定义时的上下文

这并不是很正确的答案……虽然也不是完全错误

箭头函数中的 this

首先说我的回答中没有错误的部分:箭头函数中的 this 确实和调用时的上下文无关

function make () {
  return ()=>{
    console.log(this);
  }
}
const testFunc = make.call({ name:'foo' });
testFunc(); //=> { name:'foo' }
testFunc.call({ name:'bar' }); //=> { name:'foo' }

这个例子可以看到,确实箭头函数在定义之后,this 就不会发生改变了,无论用什么样的方式调用它,this 都不会改变;

但严格来说,这并不是“取决于定义时的上下文”, 因为箭头函数根本就没有绑定自己的 this,在箭头函数中调用 this 时,仅仅是简单的沿着作用域链向上寻找,找到最近的一个 this 拿来使用罢了;
从效果上看,这和我之前的理解并没有多大偏差,但它们的本质却是截然不同,箭头函数并不是普通函数新增了 this 不受调用时上下文影响的特性,而是减少了很多特性;

箭头函数其实是更简单的函数

实际上箭头函数中并不只是 this 和普通函数有所不同,箭头函数中没有任何像 this 这样自动绑定的局部变量,包括:this,arguments,super(ES6),new.target(ES6)……

借用别人的一个例子:

function foo() {
  setTimeout( () => {
   console.log("args:", arguments);
  },100);
}
foo( 2, 4, 6, 8 );
// args: [2, 4, 6, 8]

在普通函数中,会自动绑定上的各种局部变量,箭头函数都是十分单纯的沿着作用域链向上寻找……

箭头函数就是这么个简单、纯粹的东西;

所以我个人认为箭头函数更适合函数式编程,除了它更短以外,使用箭头函数也更难被那些没有显示声明的变量影响,导致你产生意料之外的计算结果;

那么普通函数能否实现和箭头函数一样的效果呢?

如果是像当初的我一样简单的考虑固定住 this 这个易变的家伙……那倒是很简单,有些常用的方法,比如这样:

function make () {
  var self = this;
  return function () {
    console.log(self);
  }
}

或者

function make () {
  return function () {
    console.log(this);
  }.bind(this);
}

然而第二种方法只能固定 this 这一个变量而已,如前文所述,箭头函数中的 arguments 等变量也是从作用域链中寻找的,为了实现类似的效果,我们只有重新定义一个局部变量这一种方式,而 babel 也是使用这种方式对箭头函数进行处理的。

function make () {
  return ()=>{
    console.log(this);
    console.log(arguments);
  }
}
//babel it...
function make() {
  var _this = this,
    _arguments = arguments;
  return function () {
    console.log(_this);
    console.log(_arguments);
  };
}

那么……如果我想在箭头函数中使用 arguments 该怎么办?

……我觉得如果你有这个需求,可能还是用普通函数更合适一点……

但并不是说在箭头函数中无法以类似数组的形式取到所有参数,我们可以利用展开运算符来接收参数,比如这样:

const testFunc = (...args)=>{
  console.log(args) //数组形式输出参数
}

或许真的有场景需要用到这种写法,但我还是认为,箭头函数更适合那些接受固定的参数,返回一个计算结果的简单情况;

以上所述是小编给大家介绍的JavaScript中的普通函数和箭头函数的区别和用法详解,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我们网站的支持!

(0)

相关推荐

  • 深入理解JavaScript中的箭头函数

    从一开始箭头就是 JavaScript 的一部分,在第一个 JavaScript 中就建议将内联的脚本代码包裹在 HTML 的注释中,这可以防止那些不支持 JavaScript 的浏览器错误滴将你的代码显示为明文.你也许写过下面这样的代码: <script language="javascript"> <!-- document.bgColor = "brown"; // red // --> </script> <scri

  • 详解Javascript ES6中的箭头函数(Arrow Functions)

    ES6可以使用"箭头"(=>)定义函数,注意是函数,不要使用这种方式定义类(构造器). 一.语法 1. 具有一个参数的简单函数 var single = a => a single('hello, world') // 'hello, world' 2. 没有参数的需要用在箭头前加上小括号 var log = () => { alert('no param') } 3. 多个参数需要用到小括号,参数间逗号间隔,例如两个数字相加 var add = (a, b) =&g

  • javascript ES6中箭头函数注意细节小结

    前言 ES6标准新增了一种新的函数:Arrow Function(箭头函数). 为什么叫Arrow Function?因为它的定义用的就是一个箭头: x => x * x 上面的箭头函数相当于: function (x) { return x * x; } 但箭头函数带来了些许问题,下面来一起看看吧. 关于{} 第一个问题是关于箭头函数与{}. 箭头函数,乍一看,用法似乎很简单,比如像下面这样用来给数组每一项乘以2: const numbers = [1, 2, 3]; const result

  • JavaScript箭头函数_动力节点Java学院整理

    ES6标准新增了一种新的函数:Arrow Function(箭头函数). 为什么叫Arrow Function?因为它的定义用的就是一个箭头: x => x * x 上面的箭头函数相当于: function (x) { return x * x; } 在继续学习箭头函数之前,请测试你的浏览器是否支持ES6的Arrow Function 箭头函数相当于匿名函数,并且简化了函数定义.箭头函数有两种格式,一种像上面的,只包含一个表达式,连{ ... }和return都省略掉了.还有一种可以包含多条语句

  • 浅析JavaScript 箭头函数 generator Date JSON

    ES6 标准新增了一种新的函数: Arrow Function(箭头函数). x => x *x 上面的箭头相当于: function (x){ return x*x; } 箭头函数相当于匿名函数,并且简化了函数定义.一种像上面的,只包含一个表达式, 连{ ... }和return都省略掉了.还有一种可以包含多条语句,这时候就不能省略{ ... }和return: x =>{ if(x > 0){ return x * x; }else{ return -x *x; } } 如果参数不是

  • 深入理解Javascript箭头函数中的this

    首先我们先看一段代码,这是一个实现倒数功能的类「Countdown」及其实例化的过程: function Countdown(seconds) { this._seconds = seconds; } Countdown.prototype._step = function() { console.log(this._seconds); if (this._seconds > 0) { this._seconds -= 1; } else { clearInterval(this._timer)

  • Javascript中 带名 匿名 箭头函数的重要区别(推荐)

    带名函数是指函数显示地给出了一个名字的函数,function abs(x){}.匿名函数是指函数只带有function这个关键字,而没有像abs这种函数名称的函数,如function(){}.ES6标准新增了一种新的函数:Arrow Function(箭头函数)箭头函数表面上相当于匿名函数,并且简化了函数定义.它们各自的区别是什么呢? 1 带名和匿名函数的区别 区别:匿名函数需要讲地址赋值给另一个变量let a,然后再用a来调用函数:而带名函数因为显示地给出了函数名称,所以可以直接用这个函数名称

  • Javascript中Math.max和Math.max.apply的区别和用法详解

    最近在做一个小案例的时候遇到了Math.max.apply这么一个用法,之前很少遇到过感觉挺有趣的,就记录一下. 1Math.max 语法: Math.max(n1,n2,n3,...,nX) 返回值:max() 方法可返回指定的参数中带有较大的值的那个数 var a = Math.max(1,2,3,4); console.log(a); //4 但是如果数据是放在一个数组里面,此时就不能这样调用了.这时就用到apply方法 2Math.max.apply apply() 方法调用一个函数.简

  • JavaScript中的普通函数和箭头函数的区别和用法详解

    最近被问到了一个问题: javaScript 中的箭头函数 ( => ) 和普通函数 ( function ) 有什么区别? 我当时想的就是:这个问题很简单啊~(flag),然后做出了错误的回答-- 箭头函数中的 this 和调用时的上下文无关,而是取决于定义时的上下文 这并不是很正确的答案--虽然也不是完全错误 箭头函数中的 this 首先说我的回答中没有错误的部分:箭头函数中的 this 确实和调用时的上下文无关 function make () { return ()=>{ consol

  • JavaScript中最容易混淆的作用域、提升、闭包知识详解(推荐)

    一.函数作用域 1.函数作用域 就是作用域在一个"Function"里,属于这个函数的全部变量都可以在整个函数的范围内使用及复用. function foo(a) { var b = 2; function bar() { // ... } var c = 3; } bar(); // 失败 console.log( a, b, c ); // 三个全都失败 上面的"foo"函数内的几个标识符,放到函数外面访问就都会报错. 2.立即执行函数表达式 在任意代码片段外部

  • Yii2中hasOne、hasMany及多对多关联查询的用法详解

    前言 hasOne.hasMany是Yii2特有的用于多表关联查询的函数,平时在使用多表关联查询的时候建议使用它们.为什么?因为这种方式关联查询出来的结果会保留Yii2自有的表头排序功能,以及CheckboxColumn中input的id存值,至于还有没有其它的好处就需要大家去挖掘了,笔者目前就发现了这两个常用的好处.其他的关联查询,像yiidbQuery查询或者原生的SQL语句查询都没有,查询出来在列表展示的时候,表头一排黑. Yii2的hasOne.hasMany多表关联查询,不管是文档还是

  • 对vue2.0中.vue文件页面跳转之.$router.push的用法详解

    vue2.0在使用的过程中, .vue文件之间的跳转,在template中的常见写法是: <router-link to="/miniCard/statement/horizon"> <button class="btn btn-default colorDe">继续</button> </router-link> 但是有时的需求是页面不直接跳转,有确认弹框或者其他事件,此时就需要在js中设置跳转,常用的一种方法是 .

  • js中substr,substring,indexOf,lastIndexOf,split,replace的用法详解

    indexOf() 方法可返回某个指定的字符串值在字符串中首次出现的位置. lastIndexOf() 方法可返回一个指定的字符串值最后出现的位置,在一个字符串中的指定位置从后向前搜索. substring() 方法用于提取字符串中介于两个指定下标之间的字符. substr(start,length)表示从start位置开始,截取length长度的字符串 split 将一个字符串分割为子字符串,然后将结果作为字符串数组返回 replace 用于在字符串中用一些字符替换另一些字符,或替换一个与正则

  • PHP echo,print,printf,sprintf函数之间的区别与用法详解

    1. echo函数: 输出函数,是命令,不能返回值.echo后面可以跟很多个参数,之间用分号隔开,如: echo $myvar1; echo 1,2,$myvar,"<b>bold</b>"; 2. print函数: 是函数,可以返回一个值,只能有一个参数. int print ( string arg ) Outputs arg . Returns 1 , always. 3. printf函数: int printf ( string format [, m

  • JavaScript的DOM与BOM的区别与用法详解

    目录 1. 简述:何为DOM,何为BOM? 2. DOM及其相关操作 2.1DOM树 2.2DOM的一些常见的操作元素方法 获取节点的DOM方法 获取/设置元素的属性值的DOM方法 创建节点(Node)的DOM方法 增添节点的DOM方法 删除节点的DOM方法 DOM常见的一些属性 3. BOM及其相关操作 3.1 BOM总述 3.2 BOM常见对象的介绍 window对象 location对象 history对象 navigator对象 总结 1. 简述:何为DOM,何为BOM? 在文章开始之初

  • Flask框架中密码的加盐哈希加密和验证功能的用法详解

    密码加密简介 密码存储的主要形式: 明文存储:肉眼就可以识别,没有任何安全性. 加密存储:通过一定的变换形式,使得密码原文不易被识别. 密码加密的几类方式: 明文转码加密:BASE64, 7BIT等,这种方式只是个障眼法,不是真正的加密. 对称算法加密:DES, RSA等. 签名算法加密:也可以理解为单向哈希加密,比如MD5, SHA1等.加密算法固定,容 易被暴力破解.如果密码相同,得到的哈希值是一样的. 加盐哈希加密:加密时混入一段"随机"字符串(盐值)再进行哈希加密.即使密码相同

  • Python中几种属性访问的区别与用法详解

    起步 在Python中,对于一个对象的属性访问,我们一般采用的是点(.)属性运算符进行操作.例如,有一个类实例对象foo,它有一个name属性,那便可以使用foo.name对此属性进行访问.一般而言,点(.)属性运算符比较直观,也是我们经常碰到的一种属性访问方式. python的提供一系列和属性访问有关的特殊方法: __get__ , __getattr__ , __getattribute__ , __getitem__ .本文阐述它们的区别和用法. 属性的访问机制 一般情况下,属性访问的默认

随机推荐