前言
最近看到一个MS题:在实例化对象时,new函数做了什么事情?
function Person(){ //构造函数Person
...
}
var xiaoming = new Person();//xiaoming是实例化的对象
开始我是一阵恍惚,new不就是实例化出构造函数(或者类)的一个对象吗?还能做什么?后来仔细审题,发现人家就是在问new在实例化的时候到底做了什么工作,于是问题变成了:实例化对象过程发生了什么?是怎样实现的?
1 实例化对象过程发生了什么?
首先我们倒着考虑下,通过new实例化得到的对象到底是个什么东西,从而分析new函数做了什么?
- 对象是一个对象(Object),看似废话,却是关键的事实;
- 对象继承了构造函数的原型链;
- 对象拥有构造函数(类)的所有方法和属性;
以上就是new出来的对象所具有的特性,接下来需要做的就是怎样让对象具有以上特性
2 怎样实现实例化?
我们就以构造函数为例~类的实现大同小异~
-
创建一个对象-因为首先要有一个对象
var xiaoming = {};
-
继承原型链:将对象的原型指向构造函数的原型:
function Person(name, age){ //目标构造函数Person
this.name = name;
this.age = age;
}
Person.prototype.say = function () {
console.log(`我的名字叫${this.name}, 年龄${this.age}`)
}
xiaoming.__proto__ = Person. prototype;
-
绑定构造函数上下文的方法和属性:
通过apply方法改变this的指向,执行构造函数Person,将所有属性绑定在对象(xiaoming)上
Person.apply(xiaoming, ['小明', 18])
3 demo函数总结
上边我们分步实现了实例化对象的过程,下边通过一个函数整体简单复写new方法
/*
* f为传入的构造函数,
* arg为传入的参数
*/
function new_demo (f, ...arg){
var obj = {};
obj.__proto__ = f.prototype;
f.apply(obj, arg);
return obj;
}
通过new_demo函数实例化对象:
var xiaohong = new_demo(Person, '小红', 18);
xiaohong.say();//我的名字叫小红, 年龄18
总结
以上整个实现new方法的过程,就交代了new函数在实例化的过程中做了什么。简单来说,就是三步:创建对象、重置原型链指向、绑定构造函数上下文属性和方法