当前位置: 首页 > Web前端 > HTML

面试题:箭头函数和普通函数的区别

时间:2023-03-28 01:20:12 HTML

去年面试的时候,五位面试官中有三位问过这个问题。可见这是一道常见的面试题。我忘了我是怎么回答的了。现在说一下:箭头函数没有this绑定,它的this指向父作用域。果然有记不住的原因,因为没写文章,没看懂真正的答案是什么?阮一风版:箭头函数没有自己的this对象。函数体中的this是定义时的对象而不是使用时的对象。它不能用作构造函数。也就是说箭头函数不能使用new命令,否则会报arguments对象不能使用的错误,arguments对象在函数体内不存在。如果要使用,可以使用rest参数代替yield命令,所以箭头函数不能作为Generator函数使用。返回对象时,必须在对象外加上括号。Nicholas版本:没有this、super、arguments和new.target绑定。this、super、arguments和new.target的值由最近的不包含箭头函数的作用域决定,不能被new调用。箭头函数内部没有[[Construct]]方法,所以不能作为构造函数使用。使用new调用箭头函数在没有原型的情况下会抛出错误,并且由于您不能使用new来调用箭头函数,因此没有理由存在原型。箭头函数没有prototype属性,不能改变this,函数内部也不能修改this的值。this的值在函数的整个生命周期内都是不可变的。没有arguments对象,并且由于箭头函数没有参数绑定,您必须依赖命名或rest参数来访问函数的参数。不允许重复的命名参数。Nicholas在写《深入理解 ES6》的作者,阮一峰没有解释组合,也就是说,箭头函数和普通函数的区别在于不能作为构造函数,因为不能new,和之所以不能是new,是因为没有[[Construct]]方法。因为它不可能是新的,所以它没有原型,也没有它自己的this。它的this是由定义它的对象而不是使用它的对象决定的。它也没有参数。yield命令不能用于对象,也不能用于生成。下面依次说说这四点。新从哪里来?我们先回顾一下new调用构造函数执行的是什么。在内存中创建一个新对象。新对象中的[[prototype]]特征被指定为构造函数的原型属性。函数内部的this被赋值给这个新对象(this指向新对象)来执行构造函数内部的代码(给新对象添加属性)。如果构造函数返回一个非空对象,则返回该对象;否则,返回新创建的对象我们可以写一个newfunctionnew2(Constructor,...args){varobj=Object.create(null);obj.__proto__=Constructor.prototype;varresult=Constructor.apply(obj,...args)returntypeofresult==='object'?result:obj}看完new回头看看为什么不能调用newJavaScript函数内部有两个方法:[[Call]]和[[Construct]]直接调用时,执行[[Call]]方法,直接执行函数体。调用new时,执行[[Construct]]方法创建一个实例对象。箭头函数的最初设计是设计一个更短的函数,没有[[Construct]]方法。99.9%的人都不知道箭头函数不能作为构造函数的秘密,提取了很多英文资料来证明这个事实。我们可以说,因为它没有[[Construct]]内部方法,所以它不能是新的。又因为不能new,所以对prototypeprototype不了解。可以看这篇文章:prototypethis谁在JavaScript中叫你this是词法作用域,跟你在哪里定义无关,跟你在哪里调用有关,所以会出现各种各样的this“怪物”问题,有4个thisasaobjectmethodcallasafunctioncallasaconstructorcallusingapplyorcallcall但是箭头函数没有自己的this对象的方法,内部this是上层函数当在域中定义this.也就是说,箭头函数中的this指向固定参数。较旧的类数组参数是与传递给函数的参数相对应的类数组对象。arguments对象标识可用于所有(非箭头)函数的局部变量。可以说,只要是(非箭头)函数,都有自己的arguments,arguments代表传递给函数的所有参数。什么是类数组对象?index属性访问元素,有length属性的对象vararrLike={0:'name',1:'age',length:2}箭头函数没有yieldyield之前是什么意思,先搞明白thegenerator生成器是ES6新增的一个极其灵活的结构,具有在功能块内挂起和恢复代码执行的能力。生成器的形式是函数,函数名前有星号(*)表示它是生成器。Generatorscanbedefinedwherevera(non-arrow)functioncanbedefined//生成器函数声明function*generatorFn(){}//生成器函数表达式letgeneratorFn=function*(){}//asanobjectGeneratorfunctionofliteralmethodletfoo={*generatorFn(){}}//generatorfunctionasclassinstancemethodclassFoo{*generatorFn(){}}//generatorfunctionasclassstaticmethodclassBar{static*generatorFn(){}}的标识生成器函数的星号不受两边空格的影响,yield关键字允许生成器停止和开始执行,这也是生成器最有用的地方。生成器函数正常执行,直到遇到yield关键字。遇到此关键字时,执行将停止并保留函数作用域的状态。停止执行的生成器函数只能通过调用生成器对象的next()方法来恢复//umi项目中请求接口的例子*fetchData({payload},{call,put}){constresData=yield调用(fetchApi,有效负载);if(resData.code==='OK'){yieldput({type:'save',payload:{data:resData,},});}else{Toast.show(resData.resultMsg);}},因为不能用箭头函数来定义生成器函数,所以不能用yield关键字来模拟面试面试官:你知道ES6吗面试官:嗯,在项目中一直有用面试官:说说你的平时使用了哪些ES6新特性?面试官:比如箭头函数、let、const、模板字符串、展开运算符、Promise……面试官:嗯,箭头函数和普通函数有什么区别?面试官:箭头函数不能new,不带参数,它的this跟那里的定义有关,不能用yield命令,返回对象的时候必须在对象外加括号面试官:为什么箭头函数不能new面试官:因为箭头函数没有[[Construct]]方法,new的时候JavaScript会在内部调用[[Construct]]方法,因为没有箭头函数,所以new的时候会报错。当然,箭头函数是没有原型的,因为它们不可能是新的。采访者:你刚才说没有争论。我简单介绍一下。面试官:是所有参数的集合。每个(非箭头)函数都有自己的参数,它的结构是类数组对象面试官:什么是类数组对象面试官:可以通过索引访问元素的对象,有length属性...面试官:再问一下其他参考资料99.9%的入门ECMAScript6的人都不知道箭头函数不能作为构造函数来深入理解ES6的秘密。本文参与SegmentFaultthink-no-no随笔《如何“反杀”面试官?如果您正在阅读,欢迎您加入。