先说说new是做什么,怎么用的?
看代码,我们一一解释
//构造函数
function Animal(type){
this.type = type
}
Animal.prototype.say = function(){
//为了区分我们打印一个哺乳
console.log("say")
}
//实例化
let animal = new Animal('哺乳动物')
console.log(animal)//
console.log(animal.type)//打印结果是 哺乳动物
animal.say() //打印结果是 哺乳

1、首先构造函数是一个对象,证明new 返回一个对象,根据我们的测试我们暂时先这么定义
2、实例化对象可以拿到构造函数的属性
3、实例对象也可以拥有构造函数的原型上的方法和属性
下面我们根据构造函数->实例化后的一些特性来模拟new的实现。
function mockNew(){
//参数不定的情况下我们用arguments来操作,顺便用下es6的解构
//上边我们解释过,参数有两部分组成,构造函数(也就是所谓的类),参数
let [Fn,...options] = [...arguments]
console.log(Fn,options)//打印结果 Animal构造函数,和 tom/2
//返回一个对象,那我们就定义一个对象
let obj = {}
//下面我们实现对象的功能
// 怎么获得构造函数的属性 也就是让obj拿到构造函数的属性(属性都在options里面)
Fn.apply(obj,options)//执行构造函数,并把this指向obj,这样是不是就搞定了
// 接下来我们实现obj拥有构造函数原型上的方法
// 这就用到原型链了,每一个对象都有__proto__属性,每个函数都有prototype原型
// 为了能详细说明 我们再画一下
obj.__proto__ = Fn.prototype
return obj
}

//构造函数
function Animal(type){
this.type = type
}
Animal.prototype.say = function(){
//为了区分我们打印一个哺乳
console.log("我是构造函数的say方法")
}
//实例化
// let animal = new Animal('哺乳动物')
let animal = mockNew(Animal,'mock哺乳动物')
console.log('实例对象:', animal)//
console.log('实例的type属性:'+animal.type)//打印结果是 哺乳动物
animal.say() //打印结果是 哺乳
测试一下效果:

貌似没毛病!
//还有一种情况 如果构造函数有返回值 我们先测试原生new是怎么做的
function Animal1(type){
this.type = type
// return {name:"xd"} //如果是对象 new执行完 返回此对象
return type //如果是非引用类型,new的返回结果不变
}
let animal1 = new Animal1('哺乳动物1')
console.log(animal1,animal1.type)
既然是模拟 我们要做到一样的效果
function mockNew(){
//参数不定的情况下我们用arguments来操作,顺便用下es6的解构
//上边我们解释过,参数有两部分组成,构造函数(也就是所谓的类),参数
let [Fn,options] = [[...arguments][0],[...arguments].slice(1)]
console.log(Fn,options)//打印结果 Animal构造函数,和 tom/2
//返回一个对象,那我们就定义一个对象
let obj = {}
//下面我们实现对象的功能
// 怎么获得构造函数的属性 也就是让obj拿到构造函数的属性(属性都在options里面)
let result = Fn.apply(obj,options)//执行构造函数,并把this指向obj,这样是不是就搞定了
// 接下来我们实现obj拥有构造函数原型上的方法
// 这就用到原型链了,每一个对象都有__proto__属性,每个函数都有prototype原型
// 为了能详细说明 我们再画一下
obj.__proto__ = Fn.prototype
//定义result就是构造函数返回值,判断返回值是不是引用类型,如果是返回构造函数返回值,如果不是返回我们定义的obj
return result instanceof Object? result: obj
}
模拟new 操作聊完了 欢迎吐槽!
网友评论