该文章已同步至掘金
问题:箭头函数是否有原型
今天在博客重构之余,看到某个前端群有群友这样问:
面试被问到了一个题,箭头函数是否有原型
大家觉得有吗?
首先不说它是不是,我们来回顾一下 箭头函数 是什么,原型 又是什么。
箭头函数是什么
箭头函数表达式的语法比函数表达式更简洁,并且没有自己的this,arguments,super或new.target。箭头函数表达式更适用于那些本来需要匿名函数的地方,并且它不能用作构造函数。
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Functions/Arrow_functions
引入箭头函数有两个方面的作用:更简短的函数并且不绑定this。
一般来说如果问题是函数是否有原型
时,那么可以好不犹豫的回答说是有
,但因为箭头函数的特殊性导致了答案的不确定性。
原型是什么
当谈到继承时,JavaScript 只有一种结构:对象。
每个对象(object)都有一个私有属性指向另一个名为原型(prototype)的对象。
原型对象也有一个自己的原型,层层向上直到一个对象的原型为 null。
根据定义,null 没有原型,并作为这个原型链(prototype chain)中的最后一个环节。
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Inheritance_and_the_prototype_chain
一个 Function 对象在使用 new 运算符来作为构造函数时,会用到它的 prototype 属性。它将成为新对象的原型。
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Function/prototype
什么是原型在 mdn 中已经讲得很清楚了,也就是对象的prototype
。
试验
所以按理来说对象都有原型,那么试试就知道了。
首先看看箭头函数的原型:
const a = () => {};
console.log(a.prototype); // undefined
在浏览器控制台可以把上述代码执行一遍,可以发现结果是 undefined。
那么是否就说明箭头函数没有原型了呢?别急继续往下看。
const a = () => {};
console.log(a.prototype); // undefined
console.log(a.__proto__); // ƒ () { [native code] }
我们可以看到 a.__proto__ 是一个 native function
那么 __proto__ 又是什么呢?
__proto__是什么
Object.prototype (en-US) 的 __proto__ 属性是一个访问器属性(一个 getter 函数和一个 setter 函数), 暴露了通过它访问的对象的内部[[Prototype]] (一个对象或 null)。
__proto__ 的读取器 (getter) 暴露了一个对象的内部 [[Prototype]] 。对于使用对象字面量创建的对象,这个值是 Object.prototype (en-US)。对于使用数组字面量创建的对象,这个值是 Array.prototype。对于 functions,这个值是 Function.prototype。对于使用 new fun 创建的对象,其中 fun 是由 js 提供的内建构造器函数之一 (Array, Boolean, Date, Number, Object, String 等等),这个值总是 fun.prototype。对于用 JS 定义的其他 JS 构造器函数创建的对象,这个值就是该构造器函数的 prototype 属性。
__proto__ 属性是 Object.prototype (en-US) 一个简单的访问器属性,其中包含了 get(获取)和 set(设置)的方法,任何一个 __proto__ 的存取属性都继承于 Object.prototype (en-US),但一个访问属性如果不是来源于 Object.prototype (en-US) 就不拥有 __proto__ 属性,譬如一个元素设置了其他的 __proto__ 属性在 Object.prototype (en-US) 之前,将会覆盖原有的 Object.prototype (en-US)。
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/proto
看解释可能有人不大理解,举个例子 🌰:
function F() {}
const f = new F();
console.log(f.prototype); // undefined
console.log(f.__proto__ === F.prototype); // true
console.log(f.__proto__.constructor); // F(){}
new F 也即是 F 的实例 f, f 的 __proto__ 属性指向 F 的 prototype。
由此可以得出实例与原型的关系:new function得到实例,实例的 __proto__ 又指向function的原型,原型的构造器指向原函数。
结论
好了,理解了什么是 __proto__ 后,我们回到原来的问题上:箭头函数函数是否有原型?
通过上述的代码我们可以知道箭头函数就是Function的实例,如果你觉得不是,那么请看下面的例子:
const a = () => {};
console.log(a instanceof Function); // true
console.log(a.__proto__ === Function.prototype); // true
console.log(a.prototype); // undefined
所以最终得出两种结论:如果按中文语意那么箭头函数是Function的实例,而依据实例与原型的关系,它是有原型的;如果原型仅仅只说的是prototype,那么结论就是没有
注:以上代码结果都是在chrome113下运行得出
如有错误,欢迎指正~
参考
箭头函数
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Functions/Arrow_functions
构造器
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/constructor
原型链
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Inheritance_and_the_prototype_chain
Function.prototype
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Function/prototype
__proto__
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/proto
评论