构造函数和实例化
在 JavaScript
可以通过构造函数批量创建对象,这个创建的过程通过 new
关键字实现,也被称作实例化,对象被创建时会有默认的属性和原型方法。
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.sayHi = function () {
var output = "My name is " + this.name + ", I'm " + this.age + " years old."
console.log(output);
}
var panda = new Person('panda', 25);
panda.sayHi(); // My name is panda, I'm 25 years old.
new 的过程都做了什么
在
new
的过程中主要做了4
件事:
- 创建一个空对象;
- 将这个空对象的原型指向构造函数的原型;
- 执行构造函数,并将默认属性挂载到这个空对象上;
- 判断构造函数的返回值,如果是对象则返回这个对象,否则返回新创建的对象。
模拟 new 关键字
清楚了构造函数实例化的过程,我们就来手动实现一个 New
函数,来替代关键字 new
。
// New 函数的第一个参数为构造函数,剩余的参数为实例化传入的参数
function New() {
var Constructor = Array.prototype.shift.call(arguments);
var obj = {};
obj.__proto__ = Constructor.prototype;
var result = Constructor.apply(obj, arguments);
return result instanceof Object ? result : obj;
}
// 使用 New 创建实例
var panda = New(Person, 'panda', 25);
console.log(panda); // Person {name: "panda", age: 25}
panda.sayHi(); // My name is panda, I'm 25 years old.
上面的方法已经实现了 new
关键字的功能,但是美中不足的是,不能将构造函数和实例化的参数区分清晰,下面稍微优化一下。
/* 优化后 */
function New(Constructor) {
return function () {
var obj = {};
obj.__proto__ = Constructor.prototype;
var result = Constructor.apply(obj, arguments);
return result instanceof Object ? result : obj;
}
}
/* 使用 New 创建实例 */
var panda = New(Person)('panda', 25);
console.log(panda); // Person {name: "panda", age: 25}
panda.sayHi(); // My name is panda, I'm 25 years old.
与第一种相比只是 New
函数的使用方式有所变化,New
执行后返回一个函数,调用这个返回的函数,才会进行实例化,传入的参数为实例化对象的参数,这样是 New
的功能变的单一,也将构造函数与实例化的参数分开。