new-模拟实现,简单易懂

127 阅读1分钟

作用:创建一个构造函数的实例对象。

知识储备

  • 实例.proto = 类.prototype
  • apply修改this指向,同时传入参数。即把我的某个方法借用给别的对象使用,同时把参数丢入
  • 实参里第一个参数:就是构造函数

从arguments类数组中提取出,构造函数和传入的 参数

也就是分别提取 第一个、第二个元素

fn

[].slice.call(arguments)[0]//数组的slice方法会把伪数组转成数组[]shift.call(arguments)//shift:把数组的第一个元素删除并返回该元素[...arguments][0]//...是es6 的扩展运算符,把伪数组浅拷贝到空数组[]里

params

[].slice.call(arguments)[1]

  • ps:slice 或是shift方法会将具有length属性的对象(伪数组) 转换成数组
  • 伪数组:{ 0:'Macrolam', 1:'女', length:2}

实现步骤

1. 在内存中创建一个新对象

2. 获取构造函数,实参arguments伪数组里第一个

3. 连接原型,新对象可以访问原型中的属性,实例.proto = 类.prototype

4. 把构造函数当普通函数进行执行,把构造函数的this指向新对象,并且为这个新对象添加属性

5.分析函数返回值,如果构造函数本身有返回值,优先,否则,返回新对象。

代码实现

function _new(){    
    let obj = new Object()
    let constructor = [].shift.call(arguments)

    obj.__proro__ = constructor.prototype

    let result = constructor.apply(obj,arguments)
    return typeof result === 'object' ? result : obj
      
}

简单写法

function _new(fn) {
	const obj = Object.create(fn.prototype);
	result = fn.apply(obj, [...arguments].slice(1));
	return typeof result === "object" ? result : obj;
} 

var obj = Object.create(fn.prototype) 等价于:

var obj = new Object ();obj._proto_ = constructor.prototype;

测试代码

_new(Object,{name:'mac',age:22})//{name: 'mac', age: 22}