计算正方形周长面积代码优化
let squareList=[];
let widthList=[1,2,5,7,9,1,2,3,4,5,6,7];
for(let i=0;i < 11;i++){
squareList[i]={
width:widthList[i],
getArea(){
return this.width*this.width
},
getLength(){
return this.width*4
}
}
}
内存浪费分析:for循环里i一直在变,在栈里改变,对于空数组,从第0->11个,必须新生成一块内存,其中的两个函数每次需要新生成,造成重复内存太多
借助原型
此时squareList.__proto__.__proto__===Object.prototype
let squareList = []
let 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]
}
函数和原型结合
封装:把细节写到一个函数中去
let squareList = []
let 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(let i = 0; i<12; i++){
squareList[i] = new Square(widthList[i])
console.log(squareList[i].constructor)
}
new操作符
规定好的,每个js函数有prototype属性,里面存在constructor
- new X()做了那几件事
- 自动创建新对象,此时是空对象
- 自动将空对象关联他的原型,指定为X.prototype
- 将空对象作为this关键字运行构造函数
- 自动返回return this
- 构造函数X做了哪2件事
- X函数给自己添加自身属性
- X.prototype对用于保存对象的共有属性
公式
你是谁构造的,你的原型就是谁的prototype对应的对象
对象.__proto__===其构造函数的.prototype
测试题:
- let x = {},请问:x 的原型是什么?
x.__proto__的值是什么?
原型是:Object.Prototype的对象
x.__proto__ 的值也是Object.Prototype
问x的原型就是在问x.__proto__ 的值
2.let square = new Square(5),请问:square 的原型是什么?square.__proto__ 的值是什么?
square 的原型就是square.__proto__ 的值:Square.prototype
- Object.prototype 是哪个函数构造出来的?Object.prototype 的原型是什么?
Object.prototype.__proto__的值是什么?
Object.prototype 的原型没有原型,Object.prototype.__proto__的值被强行设置为null
特殊值:Object.prototype是由哪个函数构造的:
他没有爸爸妈妈,没有原型,Object.prototype.__proto__为null,他只是个简单对象而已
内存图:window里有个Object属性,存着一个地址,这个地址对应window.Object的值,里面有prototype属性,对应原型的地址
构造函数算圆的周长面积
function Cricle(radius){
this.radius=radius
}
Cricle.prototype.getArea=function(){
return Math.pow(this.radius,2)*Math.PI}
Cricle.prototype.getLength=function(){
return 2*this.radius*Math.PI}
let x=new Cricle(5)
x.getArea()
78.53981633974483
x.getLength()
31.41592653589793
终极一问
- window是Window构造的 ,可以通过constructor属性看出构造者
- window.Object是window.Function构造的
- window.Function是window.Function构造的,浏览器构造了Function,然后指定它的构造者是自己
- 关于prototype属性
- 所有函数一出生就有一个prototype属性(除了箭头函数)
- 所有prototype一出生就有一个consrtuctor属性
- 所有constructor属性一出生就保存了对应的函数的地址
- 如果一个函数不是构造函数,它依然拥有prototype属性,只不过这个属性没什么用
- 如果一个对象不是函数,那么这个对象一般来说没有prototype属性,但这个对象一般一定会有
__proto__属性
- Object.prototye 是「Object 构造出来的对象 obj」的原型,即
obj.__proto__===Object.prototype Object.__proto__是 Object 的原型,由于 Object 是函数,而所有函数的原型都是 Function.prototype,所以Object.__proto__===Function.prototype- Object.prototye 不是 Object 的原型,
Object.__proto__才是 Object 的原型(x.原型 等价于x.__proto__)
代码题
- 原型方法实现:
function Person(你来补全代码){
你来补全代码
}
let person = new Person('frank', 18)
person.name === 'frank' // true
person.age === 18 // true
person.sayHi() // 打印出「你好,我叫 frank」
let person2 = new Person('jack', 19)
person2.name === 'jack' // true
person2.age === 19 // true
person2.sayHi() // 打印出「你好,我叫 jack」
思路先构造函数,再用this加自身即新对象属性,对原型加共有属性,常为函数
function Person(name,age){
this.name=name
this.age=age
}
Person.prototype.sayHi=function(){
console.log('你好,我是'+this.name)
}
let person = new Person('frank', 18)
- class方法实现: 相对于原型方法,直接在constructor里加自身属性,在函数外创建函数对象
class Person{
constructor(name, age){
this.name = name
this.age = age
}
sayHi(){
console.log('你好,我是'+this.name)
}
}
x.__proto__ 和 X.prototype都存的是原型的地址,对象就是原型。共有属性的集合就是原型。