JS创建对象
Get Started
• 用prototype来创建对象
• 用class类来创建对象
输出12个正方形的面积和周长
• 方法:用for循环
• 问题:要创建12个对象,每个还要带2个函数当做属性,占用太多内存了
• 改进:将两个函数添加进对象的原型里,共用同一块内存
• 代码:
let squareList = []
let widthList = [1,2,3,4,5,6,7,8,9,10,11,12]
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]
}
↓
• 改进:还可以更加精简,将代码抽离到一个函数再调用
• 代码:
let squareList = []
let widthList = [1,2,3,4,5,6,7,8,9,10,11,12]
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])
}
构造函数:构造函数就是可以构造对象的函数。
封装:将逻辑细节写到一个函数里面,只需要调用传参,叫做封装。
↓
• 改进:squarePrototype原型和createSquare函数还是分散的
• 代码:
let squareList = []
let widthList = [1,2,3,4,5,6,7,8,9,10,11,12]
function createSquare(width){ //构造函数
let obj = Object.create(createSquare.squarePrototype )
// 以squarePrototype为原型创建空对象
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可以知道谁构造了这个对象
}
注意:代码上先是定义了createSquare函数,然后给函数增加了新的属性。
当createSquare函数被调用时,将自身的squarePrototype属性指定为obj的原型,
再将obj返回赋值给目标对象。
new操作符
• 代码再优化,用new
let squareList = []
let widthList = [1,2,3,4,5,6,7,8,9,10,11,12]
function Square(width){ //构造函数
this.width = width
}
Square.prototype.getArea = function(){ //把原型放到函数上
return this.width * this.width
}
Square.prototype.getLength = function(){
return this.width * 4
}
for( let i = 0; i < 12; i++ ){
squareList[i] = new Square(widthList[i])
console.log(squareList[i].constructor)
}
注意:每个函数都有prototype属性,每个prototype都有constructor属性。
总结
• new X() 操作其实自动帮我们做了很多事情,这些事情包括
自动创建一个空对象
自动将该空对象的原型(_proto_)指向 X.prototype(即将 X.prototype 保存的地址复制到空对象._proto_ 里)
自动将空对象作为 this 来运行构造函数
自动 return this
• 构造函数X
X函数本身负责给对象本身添加属性
X.prototype对象负责保护对象的共用属性
代码规范
• 大小写
所有构造函数(专门用于创建对象的函数)首字母大写
所有被构造出来的对象,首字母小写
• 词性
new后面的函数,使用名词形式
如new Person(),new Object()
其他函数一般使用动词开头
如createsquare(5),createElemnet('div')
JS重要公式,也是唯一一个公式
对象.proto = 其构造函数.prototype
注意:window.object是函数对象
Circle
• 代码
fucntion Circle(radius){
this.radius = radius
}
Circle.prototype.getArea = function(){
return Math.pow(this.radius, 2) * Math.PI
}
Circle.prototype.getLength = function(){
return this.radius * 2 * Math.PI
}
let circle = new Circle(5)
circle.radius
circle.getArea()
circle.getLength()
类型V.S.类
• 类型
类型是JS数据的分类,有七种
四基两空一对象
• 类
类的针对于对象的分类,有无数种
常见的有Array、Function、Date、RegExp等
数组对象
• 定义一个数组
let arr = [1, 2, 3]
let arr = new Array(1,2,3)//元素为1,2,3
let arr = new Array(3)//长度为3
• 数组对象的自身属性
'0'/'1'/'2'/'length'
注意:属性名没有数字,只有字符串
• 数组对象的共用属性
'push'/'pop'/'shift'/'unshift'/'join'
用法都在MDN
函数对象
• 定义一个函数
function fn(x, y){return x+y}
let fn2 = hunction fn(x, y){return x+y}
let fn = (x, y) => x+y
let fn = new Function('x','y','return x+y')
• 函数对象自身属性
'name'/'length'
• 函数对象共用属性
'call'/'apply'/'bind'
JS终极一问
• window是谁构造的
Window
可以通过constructor属性看出构造者
• window.Object是谁构造的
window.Function
因为所有函数都是window.Function构造的
函数都有prototype属性
如果一个对象不是函数,那么这个对象一般来说没有 prototype 属性,但这个对象一般一定会有 _proto_ 属性
class
里面引入了更多的概念
class Square{
static x =1
width = 0
constructor(width){
this.width = width
}
getArea(){
return this.width * this.width
}
getLength(){
return this.width * 4
}
get area2(){ //只读属性
return this.width * this.width
}
}
• 用class重写Circle
class Circle{
constructor(radius){
this.radius = radius
}
getArea(){
return Math.pow(this.radius, 2) * Math.PI
}
getLength(){
return this.radius * 2 * Math.PI
}
}
let circle = new Circle(5)
circle.radius
circle.getArea()
circle.getLength()