封装
- js 通过构造函数来实现面向对象的封装
- 构造函数存在浪费内存的问题
原型
原型对象
- 作用:可以解决构造函数浪费内存的问题
- JavaScript 规定,每一个构造函数都有一个
prototype
属性,指向另一个对象,所以我们也称为原型对象 - 这个对象可以挂载函数,对象实例化不会多次创建原型上函数,节约内存
- 可以把那些不变的方法,直接定义在
prototype
对象上,这样所有对象的实例就可以共享这些方法 - 构造函数和原型对象中的
this
都指向实例化的对象
示例代码如下:
function Star(uname, age) {
this.uname = uname;
this.age = age;
}
Star.prototype.sing = function () {
console.log('唱歌')
}
const ldh = new Star('刘德华', 30)
const zxy = new Star('张学友', 40)
ldh.sing()
console.log(ldh.sing() === zxy.sing()) // true
constructor 属性
- 每个原型对象
prototype
里面都有个constructor
属性 - 该属性指向该原型对象的构造函数
使用场景:如果需要给原型对象赋值,会覆盖原本 constructor
属性,需要手动指回构造函数,示例代码如下:
function Star() {
}
Star.prototype = {
// 需要重新指回构造函数
constructor: Star,
sing: function () {
console.log('唱歌')
},
dance: function () {
console.log('跳舞')
},
}
console.log(Star.prototype.constructor)
对象原型
对象都会有一个属性 __proto__
指向构造函数的 prototype
原型对象
__proto__
是 JS 非标准属性,谷歌浏览器里面是[[prototype]]
[[prototype]]
和__proto__
意义相同- 对象原型用来表明当前实例对象指向哪个原型对象
prototype
__proto__
对象原型里面也有一个constructor
属性,指向创建该实例对象的构造函数
原型继承
通过原型进行继承,示例代码如下:
// 公共部分放到原型对象,即父构造函数
function Person() {
this.eays = 2
this.head = 1
}
function Woman() {
}
Woman.prototype = new Person()
// 指回原来的构造函数
Woman.prototype.constructor = Woman
// 给女人添加一个方法
Woman.prototype.baby = function () {
console.log('校花')
}
new Woman().baby() // 校花
function Man() {
}
Man.prototype = new Person()
Man.prototype.constructor = Man
// new Man().baby() // 报错
原型链
只要是对象都有原型对象
查找规则:
- 当访问一个对象的属性(包括方法)时,首先查找这个对象自身有没有该属性
- 如果没有就查找它的原型(也就是
__proto__
指向的prototype
原型对象) - 如果还没有就查找原型对象的原型(
Object
的原型对象) - 依此类推一直找到
Object
为止
__proto__
对象原型的意义就在于为对象成员查找机制提供一个方向,或者说一条路线- 可以使用
instanceof
运算符用于检查一个对象是否属于某个类型(是否在原型链上)