构造函数
对象需要分类吗?
1.案例分析
例1:输出宽度不同的12个正方形的面积和周长
let squareList = []
let widthList = [5,6,5,6,5,6,5,6,5,6,5,6]
for(let i = 0; i<12; i++){
squareList[i] = {
width: widthList[i],
getArea(){
return this.width * this.width
},
getLength(){
return this.width * 4
}
}
}
代码问题:浪费了太多内存
1.1 分析
- 画内存图
1.2 问题
- 代码存在两对函数(
getArea
和getLength
)的重复,一共重复了11次
1.3 借助原型
将12个对象的共用属性放到原型里
let squarePrototype = {
getArea(){
return this.width * this.width
},
getLength(){
return this.width * 4
}
}
1.4 构造函数
构造函数就是可以构造出一个对象的函数
function createSquare(width){ //此函数叫做构造函数
let obj = Object.create(squarePrototype)
// 以 squarePrototype 为原型创建空对象
obj.width = width
return obj
}
let squarePrototype = {
getArea(){
return this.width * this.width
},
getLength(){
return this.width * 4
}
}
for(let i = 0; i<12; i++){
squareList[i] = createSquare(widthList[i])
// 这下创建 square 很简单了吧!
}
createSquare
是一个构造函数Object.create()
方法创建一个新对象,使用现有的对象(squarePrototype
)来提供新创建的对象的__proto__
- 封装:把细节写到一个函数里面,只需要调用这个函数传递一个宽度即可
1.5 构造函数和原型的结合
把原型放到函数上
let squareList = []
let widthList = [5,6,5,6,5,6,5,6,5,6,5,6]
function createSquare(width){
let obj = Object.create(createSquare.squarePrototype) // 先使用后定义?NO,这个函数还没有被调用,因此可以写在这里
obj.width = width
return obj
}
createSquare.squarePrototype = { //把原型放到函数上,结合够紧密了吗?
getArea(){
return this.width * this.width
},
getLength(){
return this.width * 4
},
constructor: createSquare //方便通过原型找到构造函数
}
for(let i = 0; i<12; i++){
squareList[i] = createSquare(widthList[i])
console.log(squareList[i].constructor)
// constructor 可以知道谁构造了这个对象:你妈是谁?
}
new操作符
用new
操作符来简化以上的逻辑
1.代码分析
function Square(width){
// 在构造函数中,this代表构造的新对象 square
//这里是添加 square 的自身属性
this.width = width
}
//添加共同属性 getArea、getLength
// 不要直接用 prototype 等于 包含函数的对象,因为会把prototype上面的constructor覆盖掉
Square.prototype.getArea = function(){
return this.width * this.width
}
Square.prototype.getLength = function(){
return this.width * 4
}
let square = new Square(5)
- 所有JS里面的函数,从出生开始就有带一个叫
prototype
的属性,这是JS之父规定用来装共用属性的,每个prototype都有一个constructor属性
f1.prototype.constructor === f1
- 而我们需要操作的是:提供被创造对象的自身属性和公用属性即可
2.总结
2.1 new X()
自动做了四件事
- 自动创建空对象
- 自动为空对象关联原型,原型地址指定为
X.prototype
- 自动将空对象作为
this
关键字运行构造函数(this
就是new
创建的空对象,在空对象里加一个width
) - 自动
return this
2.2 构造函数X
(指的Square
)
X
函数本身负责给对象本身添加属性,如this.width
主要是添加新对象的自身的属性(也就是new
创建的新对象)X.prototype
对象负责保存对象的共用属性
主要是添加新对象的共用属性
3.例子
- 注意创造的函数的时候首字母大写,说明这个函数一般是用来创造对象的,如
Square
4.问题
- JS没办法告诉构造函数需要几个参数或者参数的作用是什么,只能查文档(MDN)
如:Array
构造函数
let arr1 = new Array(3)
:创造一个长度为3的空数组
let arr2 = new Array(3,5)
:创造元素为3和5的数组
代码规范
1.大小写
- 所有构造函数(专门用于创造对象的函数)首字母大写
- 所有被创造出来的函数,首字母小写
2.词性
new
后面的构造函数,使用名词形式
如:new Person()
、new Object()
- 其他函数一般用动词开头:因为函数是个操作、动作
如:creatSquar(5)
、creatElement('div')