Js中的构造函数
在写 JavaScript
的时候,经常可以看到 new Date()
这样的语法,这里 new
的就是构造函数,我们通过 function
可以定义,而箭头函数却不行。
是什么
构造函数,其实就是一种用来创建对象的函数。
在 JavaScript 中,任何普通的 function
函数,只要你用 new
去调用它,它就被当成了构造函数。
1 | function Dog(name) { |
这里的 Dog
被当作构造函数使用,new Dog()
就相当于在“构造”一个新的 Dog
对象。
做了什么
new
关键字在背后其实做了几件事:
- 创建一个空对象:
let obj = {};
- 把这个空对象的原型指向构造函数的
prototype
:obj.__proto__ = Constructor.prototype;
- 执行构造函数,把
this
指向这个新对象:Constructor.call(obj)
- 如果构造函数返回了一个对象,就用这个对象;否则返回
obj
所以你写:
1 | function Cat(name) { |
本质上 JS 干了:
1 | let obj = {}; |
为什么普通函数可以
普通的 function
在 JS 中是可以作为构造函数使用的原因是它内部有一个 [[Construct]]
方法(这是 JS 引擎里的内部实现),这个方法支持用 new
来调用。
1 | function Apple() {} |
只要是具备 [[Construct]]
的函数,就能被 new
。
为什么箭头函数不行
我们来看个例子:
1 | const Foo = () => {}; |
箭头函数一旦用 new
调用,就直接报错:“不是构造函数”。
这是因为 箭头函数根本没有 [[Construct]]
方法。
箭头函数它从一开始就不是用来“构造对象”的,它更像是一个轻量级的函数表达式,用来写一些简洁的回调或者小函数逻辑。
不仅如此,箭头函数还有这些“不能做”的事:
- 没有自己的
this
(它会捕获外层作用域的this
) - 没有
prototype
属性 - 不能用作构造函数(就是不能
new
)
所以写:
1 | const Bar = () => { |
它连 this
都没有绑定到新对象上(捕获外层 this
),更别提用来构造了。
小结
特性 | 普通函数(function) | 箭头函数(=>) |
---|---|---|
可以被 new 调用 | ✅ 是构造函数 | ❌ 报错 |
有自己的 this | ✅ | ❌(继承外层) |
有 prototype 属性 | ✅ | ❌ |
所以说,当你想写一个“模板”来创建对象时,请用普通函数;
箭头函数适合当“工具函数”或“回调函数”,别拿它来当构造器。