一、方法过载
在构造函数中直接定义方法,在实例化的时候,每一个对象都会有一个独立的方法,不同对象的同一个方法放在了不同的内存地址上,浪费了内存资源。
function MyPlane(src) {
this.src = src
this.move = function(){
console.log('移动')
}
this.init = function() {
console.log('初始化,插入节点')
}
}
//实例化两个对象,两个对象拥有同一个move方法,但是每个对象的move方法都存在不同的内存地址中
let myPlane = new MyPlane('飞机皮肤 - 1288')
let otherPlane = new MyPlane('飞机皮肤 - 288')
console.log(myPlane.move === otherPlane.move) //返回false
二、原型
1.概念
在JS中,每一个 函数 都有一个 prototype 属性,该属性是一个指针,指向函数的原型对象,这个原型对象上的属性和方法都可以被实例共享。
格式: 构造函数.prototype.属性 = 属性值
那原型有什么作用呢?它可以解决上面我们存在的方法过载的问题,我们用prototype修改上面的代码如下:
function MyPlane(src) {
this.src = src
this.init = function() {
console.log('初始化,插入节点')
}
}
//将move方法写到构造函数的原型属性上去,这样所有的实例对象都会共享该move方法,不会另外开辟内存空间
MyPlane.prototype.move = function(){
console.log('移动')
}
//实例化两个对象
let myPlane = new MyPlane('飞机皮肤 - 1288')
let otherPlane = new MyPlane('飞机皮肤 - 288')
console.log(myPlane.move === otherPlane.move) //返回true
难点:一个对象不但可以共享自己创建的属性,还可以享有原型对象的属性
2.原型链
访问一个对象属性的时候,如果在内部找不到该属性,那么就会在原型对象中查找该属性,如果原型对象上也找不到,那么就会在原型对象的原型上查找,如此循环下去,直到到达顶层对象也没有找到该属性,那么就会返回undefined。这个就是原型链。
>>原型链中有一个 constructor 属性,是构造函数,等于创建的构造函数本身
console.log(MyPlane.prototype.constructor === MyPlane)
//返回true
>>原型链中有一个 __proto__ 属性,每一个对象都有一个该属性,该属性会指向构造函数的原型对象。
console.log(myPlane.__proto__ === MyPlane.prototype)
//输出 true