function Animal(type) {
this.type = type;
}
Animal.prototype.say = function() {
console.log('say')
}
function mockNew() {
let Constructor = [].shift.call(arguments); // 取出构造函数
let obj = {} // new 执行会创建一个新对象
obj.__proto__ = Constructor.prototype
Constructor.apply(obj, arguments)
return obj
}
let animal = mockNew(Animal, 'dog')
console.log(animal.type) // dog
animal.say() // say
1:arguments是一个类数组,以像是数组的样子取到传入的所有参数,有一个callee属性(值为被调用的方法)利用数组的shift方法拿到了第一项 也就是Animal函数,同时原来的arguments被更改,失去了第一个参数。再后面被apply拿来做参数
2:第4行的Constructor.apply(obj, arguments)
意思是在obj里执行构造函数,并且挨着arguments里剩下的参数
3:[ ]可以等价Array.prototype.shift ,也就是在arguments上执行数组的shift方法的意思
4:最后可以加一个判断,是否为对象再返回
一开始的思想:原本的函数带一个参数,直接用new的时候就要传这个参数的,所以我手写出来的new方法必须提供要执行的构造函数,以及传入的这个参数,通过arguments拿到了构造函数和参数 开始折腾就行了
下面给一个更优雅时髦的写法~
function _new() {
let target = {}; //创建的新对象
//第一个参数是构造函数
let [constructor, ...args] = [...arguments];
//执行[[原型]]连接;target 是 constructor 的实例
target.__proto__ = constructor.prototype;
//执行构造函数,将属性或方法添加到创建的空对象上
let result = constructor.apply(target, args);
if (result && (typeof (result) == "object" || typeof (result) == "function")) {
//如果构造函数执行的结构返回的是一个对象,那么返回这个对象
return result;
}
//如果构造函数返回的不是一个对象,返回创建的新对象
return target;
}
最近看了慕课 有一种新的写法
function _new(func){
var obj = object.create(func.prototype)
var result = func.apply(obj)
if(typeof result == object){
return result
}else{
return obj
}
}
主要是object.create方法,参数为new出来的实例的原型,也就是_proto_的指向
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。