一、new
“new XXX类”的时候到底做了什么呢?
- 创建了一个对象
- 让这个实例对象的__proto__ (隐式原型)指向类的prototype(显式原型)
- 对象天生会有一个属性__proto__,一般实例对象的__proto__会指向把它new出来的类的prototype
- 不明确是谁new出来的实例,那它的__proto__指向Object的prototype
- 为什么要这样呢?打个比方,小红的妈妈是Mother类的一个实例,Mother类原型上有一个方法----唠叨。那当小红的妈妈.唠叨的时候,小红的妈妈不需要自己有唠叨这个方法,她可以顺着原型链(小红的妈妈.__proto__ === Mother.prototype)找到Mother类的原型,就可以使用里面的唠叨。
- 将类当普通函数执行,并且this指向第一步创建的实例对象
- 如果执行完,返回的结果是一个引用类型值(比如对象,方法),那就返回这个结果;否则只能返回刚刚创建的实例对象
那就来写代码吧~:
/*
* @params
* Func:类
* ...params:要传递给类的参数
* @return
* 引用类型值|实例对象
*/
function _new(Func, ...params) {
//第一步--创建一个对象
let obj = {};
//第二步--让他的__proto__指向类的prototype
obj.__proto__ = Func.prototype;
//第三步--将类当普通函数执行,并且让他的this是刚刚创建的实例对象obj
let result = Func.call(obj, ...params);
//第四步--检测一下本来执行结束是不是返回的是引用类型值(null的时候typeof结果也是object,所以要排除掉),是就返回该结果,不是就返回obj
return (result !== null && /^(function|object)$/i.test(typeof result)) ? result : obj;
}
//Mother类
function Mother(name) {
this.name = name;
}
Mother.prototype.laodao = function laodao() {
console.log("你怎么还不起床??");
}
//来试试写的new行不行
let mother = _new(Mother, "DaHong");
mother.laodao();// =>你怎么还不起床??
可是__proto__在IE是被保护起来的,所以来优化一下:
function _new(Func, ...params) {
//第一步--创建一个对象 + 第二步--让他的__proto__指向类的prototype
let obj = Object.create(Func.prototype);
//第三步--将类当普通函数执行,并且让他的this是刚刚创建的实例对象obj
let result = Func.call(obj, ...params);
//第四步--检测一下本来执行结束是不是返回的是引用类型值(null的时候typeof结果也是object,所以要排除掉),是就返回该结果,不是就返回obj
return (result !== null && /^(function|object)$/i.test(typeof result)) ? result : obj;
}
二、Object.create()
既然刚刚优化的时候用到了Object.create(params),那就一起分析+手写一下吧?
创建一个空对象将该对象的__proto__j指向传递进来的形参
等等!!这个第二步是不是和new能完成的第二步很像,只是new是指向new的那个类。所以我们可以借助new写这个函数(因为还是要考虑__proto__不能在IE下操作)。既然要借助new,那是不是得要有一个类,那步骤就是如下~
- 创建一个类(空函数)
- 让类的prototype指向传进来的params
- new 第一步创建的类并返回(那么按照new会做的事情,是不是创建出来的实例的__proto__就可以指向类的prototype,也就是params了呢~~)
所以代码如下~
Object.create = function create(params) {
// 第一步
function Func() {};
// 第二步
Func.prototype = params;
// 第三步
return new Func;
}
优化一下,如果传递进来的params不是个对象,就扔个错误~
Object.create = function create(params) {
if (params === null || typeof params !== "object") {
throw new TypeError("Object prototype may only be an Object");
}
// 第一步
function Func() { };
// 第二步
Func.prototype = params;
// 第三步
return new Func;
}
完成啦~~~
版权声明:本文为weixin_44044238原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。