JavaScript 模拟new的实现

首先一句话解释一下new:

new 能够实现一个对象继承构造函数的属性以及方法数组

举个例子:bash

function Parent(name,age){
  this.name = name;
  this.age = age;
}

Parent.prototype.sayName = function(){
  console.log(`my name is ${this.name}`)
}

let child = new Parent('js',18);

console.log(child.name);    // js
console.log(child.age);     // 18
child.sayName();            // my name is js
复制代码

从这个案例,能够看到实例childapp

1.继承了构造函数里面的属性函数

2.能够访问到构造函数prototype中的属性测试

经过下面这个图来直观感觉一下,这里涉及到js原形以及原型链,先提早补脑一下 ui

proto 指的是实例对象的原形链,每一个对象都有这个属性,它只想构造函数的原形;而prototype属性是函数对象才有的属性,那什么是函数对象?就是凡是经过new functioin()出来的就是函数对象。

child.constructor === Parent //true

child._proto === Parent.prototype //true

Parent.prototype.constructor === Parent //true
复制代码

接下来按照刚刚的例子结合上面的这张图片来实现new 内部是怎么的实现过程:this

function newFactory(){
	let obj = new Object(),
	    context = Array.prototype.shift.call(arguments); 
	    
	 obj.__proto__ = context.prototype;
	context.apply(obj,arguments);
	return obj;
}
复制代码
  1. 首先经过new Object()新建一个对象 obj;
  2. 取出第一个参数,就是咱们要传入的构造函数。由于 shift 会修改原数组,因此 arguments 会被去除第一个参数.
  3. 讲obj的原形指向构造函数
  4. 使用apply改变构造函数的this指向,这样obj就能够访问到构造函数的属性

接下来测试一下spa

function Parent(name,age){
  this.name = name;
  this.age = age;
}

Parent.prototype.sayName = function(){
  console.log(`my name is ${this.name}`)
}

function newFactory(){
  let obj = new Object(),
      context = Array.prototype.shift.call(arguments); 
	    
  obj.__proto__ = context.prototype;
  context.apply(obj,arguments);
  return obj;
}
let child = newFactory(Parent,'js','18')

console.log(child.name);    // js
console.log(child.age);     // 18

child.sayName();            // my name is js
复制代码

到这一步咱们已经完成了80%,由于还有种状况咱们没有考虑到,当构造函数有返回值的时候,实例化的对象会怎么?prototype

function Parent(name,age){
  this.age = age;
  this.sex = 'boy'
  return {
     name:name,
     address:'china'
  }
}

var child = new Parent('js','18')

console.log(child.name);    // js
console.log(child.age);     // undefined
console.log(child.sex);    // undefined
console.log(child.address);     // china
复制代码

经过上面这个案例,能够看出当构造函数返回了一个对象的化,实例child只能访问到返回对象的属性,那若是返回的是基本类型呢?code

function Parent(name,age){
  this.age = age;
  this.sex = 'boy'
  return 'china';
}

var child = new Parent('js','18')

console.log(child.name);    // undefined
console.log(child.age);     // 18
console.log(child.sex);    // boy
console.log(child.address);     // undefined
复制代码

从这个案例能够看出来当构造函数返回值是基本类型的时候,跟没有返回值同样。

终极版 四大步骤:

一、建立一个空对象,而且 this 变量引用该对象,// let obj = new Object();

二、继承了函数的原型。// obj.proto = func.prototype;

三、属性和方法被加入到 this 引用的对象中。并执行了该函数func// func.call(target);

四、新建立的对象由 this 所引用,而且最后隐式的返回 this 。// 若是func.call(target)返回的res是个对象或者function 就返回它

function newFactory(){
  let obj = new Object(),
      context = Array.prototype.shift.call(arguments); 
    
   obj.__proto__ = context.prototype;
   let res = context.apply(obj,arguments);
 
   if ((typeof res === "object" || typeof res === "function") && res !== null) {
      return res;
  }
  return obj;
}

复制代码
相关文章
相关标签/搜索