介绍
对于构造函数的使用很多人都很熟悉,但是对其原理很多也是比较模糊的,虽然这并不影响使用,但是熟悉了原理,才会少犯错。简单叙述下,算是给自己加深个印象。
构造函数的使用
想必都很熟悉1
2
3
4
5
6
7function Foo(name, age){
this.name = name;
this.age = age;
}
var foo = new Foo('xiaoming', 15)
// {name: "xiaoming", age: 15}
构造函数名的首字母是大写,但却并不是非得是大写,只是一种惯例,为了区别其他函数,构造函数始终都应该以一个大写字母开头,而非构造函数则应该以一个小写字母开头。所以即使你小写也不会有问题,但是肯定不建议这么做,提出来也只是为了让你注意不要小写首字母。
构造函数也是函数,只不过它可以用来创建对象。不过必须使用new
操作符,使用new
创建实例会经历4个步骤:
- 创建一个新对象
- 将构造函数的作用域赋给新对象(this指向新对象)
- 执行构造函数中的代码(this赋值)
- 返回新对象
总结:
- 函数名首字母大写
- 没有显示创建对象
- 直接将属性和方法赋给了this对象
- 没有return 语句(默认存在)
内部原理
根据上面的4个步骤,不难知道构造函数的内部原理,每当声明一个构造函数时:
- 在函数体最前面隐式的加上
this = {}
- 执行
this.xxx = xxx
- 隐式地返回
this
如:1
2
3
4
5
6function Foo(name, age){
var this = {}; //隐式加上
this.name = name;
this.age = age;
return this; //隐式返回
}
为了验证是否正确,我们可以自己实现一个构造函数,不过不是使用this
,而是使用that
:
1 | function Foo(name, age){ |
注意,这时我们不需要使用new
操作符了,因为所有需要的步骤我们都已经添加了,这就是一个普通的函数,返回一个对象。
关于返回值
我们都知道,构造函数默认返回了this
,那么假使我们自己不小心添加了return
语句会怎么样呢。不妨试一下:
1 | function Foo(name, age){ |
显然,添加return this
是不会有什么问题的。
现在我们返回一个普通值:1
return 123;
如果你试了,会发现也不会影响结果,如果你再顺便试了一下返回字符串和布尔值,发现依旧不会影响结果。现在你知道我想说啥了,没错,当你试着返回一个对象时,结果就是那个对象了,继续试着返回数组和函数,也会影响结果,使得构造函数失去应有的作用。
总结
- 构造函数默认返回了
this
- 如果手动返回了值类型,对结果没影响
- 如果手动返回了引用类型,该构造函数失效