面试常考点:模拟new实例化

先来这么一段代码

function Preson(name, age) {
  this.name = name;
  this.age = age;
  this.say = function () {
    console.log("我叫:" + this.name, "今年:" + this.age + "岁了!");
  };
}
let p = new Preson("朱莉", 19);
console.log("p", p);


定义一个p去接收实例化出来的结果,可以看到p上面有三个属性值,那么say是p上面的函数

 调用say函数

p.say();

展开一下,可以看出p的原型链结构: 

 我们打印一下这两个值发现,是一样的

console.log(Preson.prototype);
console.log(p.__proto__);

 

 那么也就是说 p.__proto__ === Preson.prototype,当然在控制台输出是true

console.log(p.__proto__ === Preson.prototype);

 那么知道new实例,其实就是操作原型链继承,那么我们就知道原理是怎么样的了

那么我们来定义一个函数来模拟一下new实例的过程:

function myNew() {
  const child = {}; //新定义一个空对象
  const parent = [].shift.call(arguments); //取出要实例化的函数,剩余的就是参数
  child.__proto__ = parent.prototype; //原型链指向要实例化的函数
  parent.apply(child, arguments); //执行函数把this指向新的对象,传入参数
  return child; //返回新创建的对象
}

 运行一下,发现结果满足需求

let child = myNew(Preson, "朱莉", 19);
console.log("child", child);
child.say();

 那么还有一个问题就是,构造函数可能有返回值,那么构造函数可能下面这种情况

function Preson() {
  return function (name) {
    console.log("hello:" + name);
  };
}

 那么刚刚写的myNew函数就会出现下面这种情况

let child = myNew(Preson, "朱莉", 19);
child("朱莉");

 那么我们需要考虑返回值是什么类型,有可能是基础类型也可能是引用类型

测试发现:返回值如果是引用类型的话(包括函数,数组和对象)返回的就是构造函数的返回值,否则就是我们继承原型链的新对象,那么我们修改一下代码得到最终代码

function myNew() {
  const child = {}; //新定义一个空对象,这里不采用Object.create(null)是因为创建出来的没有原型链
  const parent = [].shift.call(arguments); //取出要实例化的函数,剩余的就是参数
  child.__proto__ = parent.prototype; //原型链指向要实例化的函数
  const result = parent.apply(child, arguments); //执行函数把this指向新的对象,传入参数接收一下,因为可能构造函数有返回值
  return result instanceof Object ? result : child; //如果构造函数的返回值是对象,直接返回返回值,如果不是就返回新创建的对象
}

let child = myNew(Preson);
child("朱莉");

 

还可以使用Object.create

function myNew() {
  const parent = [].shift.call(arguments); //取出要实例化的函数,剩余的arguments就是参数
  const child = Object.create(parent.prototype);//创建一个空对象,并使它的原型链指向要new出来的构造函数的实例
  const result = parent.call(child, ...arguments); //执行函数把this指向新的对象,传入参数接收一下,因为可能构造函数有返回值
  return result instanceof Object ? result : child; //如果构造函数的返回值是对象,直接返回返回值,如果不是就返回新创建的对象
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值