构造函数
我们经常说new一个对象,说明通过new,我们可以创建出一个对象。那么除此之外,还发生了什么呢?
先来看一个代码
function Fun(name){
this.name=name;
}
Fun.prototype={
constructor:Fun,
say(){
console.log(this)
}
}
let a =new Fun('liudehua')
上面代码中,我设置一个构造函数Fun,然后设置Fun的原型对象,最后让new出一个实例对象a。
上面代码总共会实现以下内容:
1、创建一个构造函数
2、new一个实例对象
3、实例对象拿到构造函数中的属性
4、实例对象a可以调用构造函数原型中的方法。
要了解上面内容,我们首先需要明白原型,因为这在js中至关重要。
原型配对
我们需要明白原型图的基本构造
- 当我创建构造函数Fun时,实际上会产生两样东西,分别是
Fun.prototype
和Fun.__proto__
。
根据js公理:对象的__proto__
=== 其构造函数的prototype
我们能知道Fun
的__proto__
指向的是Function
的prototype
。
每个函数的产生都会有一个prototype
,我们通过打印可以知道Fun的prototype
里面包含的内容。
可以看到里面具有一个say
方法,这个方法是共用方法,只要使用构造函数new出来的对象都能使用prototype
的方法。
接着我们来查看一下对象a的结构
继续根据js公理对象的__proto__
=== 其构造函数的prototype
,可以得出结论:a.__proto__ === Fun.prototype
那么我们知道当new了之后,创建出来的对象的__proto__
都会被js默认设置指向到其构造函数的prototype
中。
this指向
通过new关键字,还将让构造函数中的this指向到新创建的对象中
你可以这样理解
var a=new Fun("liudehua")
new 之后//
function Fun(name){
newObj={}
newObj.name=name;
return newObj
}
new
只是对调用后的Fun
做了一些额外的处理罢了,构造函数实际上只是对函数的构造调用。调用我们已经知道是什么了,构造就是new
把新创造的对象绑定在Fun
函数内的this
上。
结论
我们可以得出通过new一个构造函数后,发生了什么
- 创建了一个对象
- 执行构造函数,并且把属性方法设置给了对象
- 把this的指向指向给对象
- 将对象的
__proto__
跟函数的Prototype
做对应
不通过new来模拟一个构造函数
通过以上结论,我们来模拟构造函数的new,把任务分为以下部分:
1、返回一个对象
2、让对象获得构造函数的属性
3、将对象的__proto__
跟函数的ptorotype
做对应
4、模拟this
function fun(name){
let obj={
name:name
};
obj.__proto__=fun.prototype
return obj
}
fun.prototype={
constructor:fun,
say(futureObj){//请查看注释
console.log(futureObj)
},
}
上面的代码返回一个对象,并且已经设置好让obj的__proto__
指向fun的prototype
,指的注意的几个点是:
- 由于重新设置了
prototype
,所以我们要重新加上constructor
- futureObj取代this,把this当成参数来传递,所以调用say()方法时,我们需要使用。
let a=fun('liudehua')
a.say(a) //使用这种方法来取代this
优化代码
我们可以使用Object.create()
来创建一新个对象并且给它指定ptototype
function fun(name){
let obj=Object.create(fun.prototype)
//obj.name = name 遇到属性很多的情况,这种写法就会很烦
//我们可以用Object.assign()方法来批量增加
Object.assign(obj,{
name:name
})
return obj
};
fun.prototype={
constructor:fun,
say(futureObj){
console.log(futureObj)
},
}
参考链接: