一、关键字new做了什么
在面试中,我们常常会被问及new
的作用,如下列代码:
const obj = new Base();
new
实际上做了三步工作,以代码来说明:
const obj = {}; // 创建一个空对象
obj.__proto__ = Base.prototype; // 将空对象的__proto__指向构造函数的prototype属性
Base.call(obj); // 将构造函数的this指向obj,并调用构造函数
总结一下:
- 创建一个空对象
- 将空对象的
__proto__
属性指向构造函数的prototype
- 将构造函数中的
this
指向空对象并且调用构造函数 - 如果构造函数有返回对象,则
new
返回这个对象,反之,则返回新创建的对象
new创建的新对象可以:
- 访问到构造函数中的属性
- 访问到构造函数原型链上的属性
function Person(name,age){
this.name = name;
this.age = age;
this.sex = 'male';
}
Person.prototype.isHandsome = true;
Person.prototype.sayName = function(){
console.log(`Hello , my name is ${this.name}`);
}
let handsomeBoy = new Person('Nealyang',25);
console.log(handsomeBoy.name) // Nealyang
console.log(handsomeBoy.sex) // male
console.log(handsomeBoy.isHandsome) // true
handsomeBoy.sayName(); // Hello , my name is Nealyang
二、模拟实现new
function objectFactory() {
let obj = new Object(); // 创建一个空对象.
Constructor = Array.prototype.shift.call(arguments); // 获取传入的第一个参数,即构造器
const fNOP = function(){};
fNOP.prototype = Constructor.prototype;
obj = new fNOP();
const ret = Constructor.apply(obj,arguments); // 构造函数的this指向obj并调用构造函数
return typeof ret === 'object'? ret:obj;
}
- 以
new Object()
的方式新建一个对象obj
- 取出第一个参数,就是我们要传入的构造函数,因为此处
shift
会修改原数组,所以arguments
会去除第一个参数 - 将
obj
的原型指向构造函数,这样obj
就可以访问构造函数原型上的方法 - 将构造函数的
this
指向obj
,并执行构造函数,接受返回结果 - 如果构造函数返回一个对象,那么返回这个对象,否则返回新建的对象
来测试一下
function Person(name,age){
this.name = name;
this.age = age;
this.sex = 'male';
}
Person.prototype.isHandsome = true;
Person.prototype.sayName = function(){
console.log(`Hello , my name is ${this.name}`);
}
function objectFactory() {
let obj = new Object(); // 创建一个空对象
Constructor = Array.prototype.shift.call(arguments); // 获取传入的第一个参数,即构造器
const fNOP = function(){};
fNOP.prototype = Constructor.prototype;
obj = new fNOP();
const ret = Constructor.apply(obj,arguments); // 构造函数的this指向obj并调用构造函数
return typeof ret === 'object'? ret:obj;
}
let handsomeBoy = objectFactory(Person,'Nealyang',25);
console.log(handsomeBoy.name) // Nealyang
console.log(handsomeBoy.sex) // male
console.log(handsomeBoy.isHandsome) // true
handsomeBoy.sayName(); // Hello , my name is Nealyang