一、构造函数
实例
写一段代码,输出一个正方形的周长和面积
let square = {
width:5,
getArea(){
return this.width * this.width
},
getLength(){
return this.width * 4
}
}
输出多个正方形的周长和面积
let square1 = {
width:5,
getArea(){
return this.width * this.width
},
getLength(){
return this.width * 4
}
}
let square2 = {
width:6,
getArea(){
return this.width * this.width
},
getLength(){
return this.width * 4
}
}
...//这种方法写起来太累
使用循环
squareList = []
for(let i=0;i<12;i++){
let squareList[i] = {
width:5,
getArea(){ //函数getArea会被重复创建11次
return this.width * this.width
},
getLength(){ //函数getLength会被重复创建11次
return this.width * 4
}
}
}
这是一段浪费内存的代码
借助原型
squareList = []
widthList = [5,6,5,6,5,6,5,6,5,6,5,6]
let squarePrototype = {
getArea(){
return this.width * this.width
},
getLength(){
return this.width * 4
}
}
for(let i=0;i<12;i++){
squareList[i] = Object.create(squarePrototype) //将面积和周长函数添加到原型中,成为共有属性
squareList[i].width = widthList[i]
}
但是,代码过于分散
将创建squareList[n]的过程写成一个函数
squareList = []
widthList = [5,6,5,6,5,6,5,6,5,6,5,6]
function createSquare(width){ //这个函数叫做构造函数
let obj[width] = Object.create(squarePrototype) //以 squarePrototype 为原型创建一个空对象
obj[width].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]]
}
但是,原型squarePrototype和构造函数createSquare()是分散的
将原型放到函数中(使函数和原型可以互相查找)
squareList = []
widthList = [5,6,5,6,5,6,5,6,5,6,5,6]
function createSquare(width){ //这个函数叫做构造函数
let obj[width] = Object.create(createSquare.squarePrototype) //以 squarePrototype 为原型创建一个空对象
obj[width].width = width
return obj
}
let 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)
}
使用new操作符,函数和原型结合
squareList = []
widthList = [5,6,5,6,5,6,5,6,5,6,5,6]
function Square(width){
this.width = width
}
Square.prototype.getArea = function(){return this.width * this.width}
Square.prototype.getLength = function(){return this.width * 4}
for(i=0;i<12;i++){
squareList[i] = new Square(widthList)
console.log(squareList[i].constructor)
}
每个函数都有 prototype 属性
每个 prototype 都有 constructor 属性
总结
new X() 做了哪些事情
- 自动创建空对象
- 自动为空对象关联原型,原型地址指定为 X.prototype
- 自动将空对象作为 this 关键字运行构造函数
- 自动 return this
构造函数X
- X 函数本身负责给对象自身添加属性
- X.prototype 对象负责保存对象的共用属性
举例
Dog(name)
function Dog(name){
this.name = name
this.color = 'white'
this.kind = 'bixiong'
}
Dog.prototype.talk = function(){console.log('talking')}
Dog.prototype.run = function(){console.log('running')}
let dog1 = new Dog('Jack')
let dog2 = new Dog('Lucky')
注意事项
大小写
- 所有构造函数(专门用于创建对象的函数),首字母大写
- 所有被构造出来的对象,首字母小写
词性
- new 后面的函数,使用名词,如 new Person()、new Object()
- 其他函数,一般使用动词开头,如 createSquare()、createElement('div')
二、对象的原型和构造函数的关系
原型公式
对象._proto_ === 构造函数.prototype
小练习
第一个
let x = {}
1、x的原型是什么? 答:Object.prototype === x._proto_
2、x.__proto__的值是什么? 答:window.Object.prototype的地址
第二个
let square = new Square(5)
1、square的原型是什么? 答:Square.prototype
第三个
1、Object.prototype 是哪个函数构造的? 答:它没有父母,是个根对象。
2、Object.prototype 的原型是? 答:Object.prototype._proto_ === null,根对象没有原型,值是null。
三、对象的分类
为什么对象需要分类?
- 很多对象拥有相同的属性,它们属于同一类
- 对象也有不同的属性,需要将它们归为不同的类,比如Array、Function属于不同的类,Object创建出来的对象是最没有特点的对象
类型和类的区别
类型
JS数据的分类,四基两空一对象,共7种:number、string、bool、symbol、null、undefined、object
类
- 针对对象的分类,有无数种
- 常见的:Array、Function、Date、RegExp
数组对象
定义
- let arr = [1,2,3]
- let arr = new Array(1,2,3)
- let arr = new Array(3)
自身属性
- [1,2,3]的自身属性:'0'、'1'、'2'、'length'
共有属性
- arr._proto_ 中的所有属性,比如'push'、'pop'、'shift'、'unshift'、'join'...
- arr._proto_._proto_ === Object.prototype,数组对象的原型的原型即obj对象的原型
函数对象
定义
- function fn(x,y){return x+y}
- let fn = function fn(x,y){return x+y}
- let fn = (x,y) => x+y
- let fn = new Function('x','y','return x+y')
自身属性
'name'/'length'/'prototype',函数自带一个prototype属性
共有属性
'call'/'apply'/'bind'
四、JS的终级问题
window是什么构造的?
window是Window构造的
window.constructor === Window,返回true
window.Object是什么构造的
window.Function,所有函数对象都是它构造的
window.Function是什么构造的
window.Function,浏览器构造了Function并指定它的构造者是自己
五、类class
class写法
class Square{
constructor(width){
this.width = width
}
getArea(){
return this.width * this.width
}
getLength(){
return this.width * 4
}
}
prototype写法
function Square(width){
this.width = width
Square.prototype.getArea = function(){
return this.width * this.width
}
Square.prototype.getLength = function(){
return this.width * 4
}
}