JS实现面向对象需要借助于构造函数来实现,构造函数存在浪费内存的问题。为了解决此问题,通常会利用原型对象方法实现共享。任何函数只要使用new操作符调用的就是构造函数,而不使用new操作符调用的函数就是普通函数
1. 原型对象
-
构造函数通过原型分配的函数是所有对象所共享的;
-
javascript规定,每一个构造函数都有一个prototype属性,指向另一个对象,也称为原型对象;
-
原型对象上可以挂载函数,对象实例化不会多次创建原型上的函数,节约内存;
-
可以把那些不变的方法,直接定义在prototype对象上这样所有的实例就可以共享这些方法;
-
构造函数和原型对象中的this都指向实例化的对象;
let that
function Person(name) {
this.name = name
}
Person.prototype.sayName = function () {
console.log(this.name)
that = this
}
let jack = new Person('jack')
let tom = new Person('tom')
jack.sayName()
tom.sayName()
console.log(jack.sayName === tom.sayName) // true
console.log(tom === that) // true
console.log(tom.constructor == Person) // true
console.log(Person.prototype.constructor == Person)
2. constructor属性
每个原型对象里面都有个constructor属性(constructor构造函数),该属性指向该原型对象的构造函数`
function Person(name) {
this.name = name
}
Person.prototype = {
constructor: Person, // 重新指回这个原型对象的构造函数
sing: function() {
console.log('sing')
},
dance: function() {
console.log('dance')
}
}
console.log(Person.prototype)
如果有多个对象的方法,可以给原型对象采取对象赋值的的形式,但这样会覆盖构造函数原型对象原来的内容,导致原型对象constructor不再指向当前构造函数,此时,可以在修改后的原型对象中添加一个constructor来指向原来的构造函数。
3. 对象原型
对象都有一个属性__proto__,指向构造函数的prototype原型对象,之所以实例对象可以使用构造函数的prototype原型对象的属性和方法,就是因为对象有__proto__原型的存在。
__proto__是JS的非标准属性,有的浏览器的写法是[[prototype]],两者意义相同,用来表明当前实例对象指向哪个原型对象prototype,__proto__对象原型里面也有一个constructor属性,指向创建该实例对象的构造函数。
function Person(name) {
this.name = name
}
let david = new Person()
console.log(david.__proto__ === Person.prototype) // true
console.log(david.__proto__.constructor === Person) // true