? ? ? ? 面对对象编程就是把事务分解成一个个对象,再由对象分工合作来解决不同的问题,更注重功能而不是步骤;
????????优点:易于维护、复用与扩展,能够设计出低耦合的系统,使得系统更加灵活、易于维护
????????缺点:性能较面对过程要低。
?????????JavaScript面对对象编程可以通过构造函数来实现封装,把公共的属性和方法封装到构造函数里面以实现数据和方法的共享,如下:
function Fruit(name) {
this.name = name
this.buy = function() {
console.log('buy'+this.name)
}
}
const orange = new Fruit('橘子')
const apple = new Fruit('苹果')
console.log(orange.buy === apple.buy) //false
????????从上面的代码可以看到,不同实例指向的buy函数并非同一函数,每构造一个新的实例就会创造一个新的buy函数,存在浪费内存的问题,这一问题可以通过原型对象得到解决。
? ? ? ? JavaScript规定,每一个构造函数都有一个prototype属性,指向另一个对象,被称为原型对象。在原型对象上挂载函数,则对象实例化时就不会多次创建原型对象中的函数,能够节约内存,如下:
function Fruit(name) {
this.name = name
}
Fruit.prototype.buy = function() {
console.log('buy')
}
const orange = new Fruit('橘子')
const apple = new Fruit('苹果')
console.log(orange.buy === apple.buy) //true
????????构造函数和原型对象中的this都指向实例化的对象;
注意:
? ? ? ? 每个原型对象中都有个constructor属性,该属性指向该原型对象的构造函数,如下:
function Fruit(name) {
this.name = name
}
console.log(Fruit.prototype.constructor === Fruit) //true
使用场景:
? ? ? ? 对原型对象直接赋值的时候,手动添加constructor属性,使得赋值后的原型对象依然指向该原型对象的构造函数,如下:
function Fruit(name) {
this.name = name
}
Fruit.prototype = {
constructor:Fruit,
buy() {
console.log('买水果')
},
sell() {
console.log('卖水果')
}
}
????????每个对象都会有一个__proto__属性指向构造函数的prototype原型对象,之所以对象可以使用构造函数prototype原型对象的方法,就是因为对象有__proto__原型的存在,如下:
function Fruit(name) {
this.name = name
}
const orange = new Fruit('橘子')
console.log(orange.__proto__ === Fruit.prototype) //true
注意:
????????构造函数中的prototype属性指向构造函数的原型对象,原型对象中的constructor属性指向该原型对象的构造函数,构造函数通过new创建新的实例对象,实例对象中的__proto__属性指向其原型对象,如图:?