自调用构造函数
4.自调用函数构造
==============
**知识点**
1.中间对象的缺点
2.自调用的原理
-----------------------------------------------------------
1.中间对象的缺点
--------------
添加到构造函数原型对象中的共享成员全部失效,不能使用
-----------------------------------------------------------
2.2.自调用的原理
--------------
- 在构造函数内部检测this是否它的一个实例,如果不是,就直接用new实例化
- 如果是实例,则按构造函数的正常流程,添加新成员到新对象上再返回
-----------------------------------------------------------
### 示例代码: code/demo04.html
```html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>自调用构造函数</title>
</head>
<body>
<script>
//上节课使用中间对象,来解决用户忘记用new来调用构造函数,但仍能正确生成实例的问题
// 其实这种中间对象机制是有一个致命bug, 就是添加到构造函数原型对象上的共享成员不能在实例中使用
var Book1 = function (name,price) {
var that = {};
that.name = name;
that.price = price;
that.getInfo = function () {
return '[' + this.name + ']' + ' 价格是: ' + this.price + ' 元';
};
return that;
};
var book1 = new Book1('JavaScript权威指南', 129);
console.log(book1.getInfo());
// 如果给这个构造函数的原型对象上添加一个共享属性:出版社
Book1.prototype.publish = '机械工业出版社';
// 发现,根本访问不到这个原型对象上的属性
console.log(book1.publish); // undefined
//这是什么呢? 因为book1对象,根本就不是Book的实例,所以不可能继承Book原型对象上的成员
console.log(book1 instanceof Book1); // false
// 怎样才能解决这个问题呢? 使用本节课介绍 的自调用构造函数就可以
var Book2 = function (name,price) {
// 检测构造函数中的this,究竟是不是当前构造函数的一个实例
// 如果不是,那么直接在这里使用 new 来调用这个构造函数(如果有传参,记得带上)
if (!(this instanceof Book2)) {
return new Book2(name,price);
}
// 以下代码是常规的添加对象成员操作
this.name = name;
this.price = price;
this.getInfo = function () {
return '[' + this.name + ']' + ' 价格是: ' + this.price + ' 元';
};
};
// 给原型对象上添加共享成员
Book2.prototype.publish = '机械工业出版社';
// 使用new 调用
var book2 = new Book2('JavaScript高级程序设计', 99);
console.log(book2 instanceof Book2);
console.log(book2.getInfo());
console.log(book2.publish); // 访问原型上的成员
// 不使用new 调用
var book3 = Book2('JavaScript高级程序设计', 99);
console.log(book3 instanceof Book2);
console.log(book3.getInfo());
console.log(book2.publish); // 结果依然正确, 完美解决问题
</script>
</body>
</html>
```