首页 /  技术专区  /  JavaScript 宽屏模式 >

JavaScript 对象原型、原型继承、原型链

1. 对象原型

对象都会有一个属性 __proto__ 指向构造函数的 prototype 原型对象,之所以我们对象可以使用构造函数 prototype原型对象的属性和方法,就是因为对象有 __proto__ 原型的存在。

Image.png

注意:

 __proto__ 是JS非标准属性

[[prototype]]和__proto__意义相同

 用来表明当前实例对象指向哪个原型对象prototype

 __proto__对象原型里面也有一个 constructor属性,指向创建该实例对象的构造函数


2. 原型继承

继承是面向对象编程的另一个特征,通过继承进一步提升代码封装的程度,JavaScript 中大多是借助原型对象实现继承的特性。

龙生龙、凤生凤、老鼠的儿子会打洞描述的正是继承的含义。

我们来看个代码:

function Man() {
    this.head = 1
    this.eyes = 2
    this.legs = 2
    this.say = function() {}
    this.eat = function() {}
}
const man = new Man()

function Woman() {
    this.head = 1
    this.eyes = 2
    this.legs = 2
    this.say = function() {}
    this.eat = function() {}
    this.baby = function() {}
}
const woman = new Woman()


1. 封装-抽取公共部分

把男人和女人公共的部分抽取出来放到人类里面

// 人类
const People = {
    head: 1,
    eyes: 2,
    legs: 2,
    say: function() {},
    eat: function() {}
}
// 男人
function Man() {
}
// 女人
function Woman() {
    this.baby = function() {}
}


2. 继承-让男人和女人都能继承人类的一些属性和方法

 把男人女人公共的属性和方法抽取出来 People

 然后赋值给Man的原型对象,可以共享这些属性和方法

 注意让constructor指回Man这个构造函数

// 人类 公共的属性和方法
const People = {
    head: 1,
    eyes: 2,
    legs: 2,
    say: function() {},
    eat: function() {}
}
// 男人
function Man() {
}
// 把公共的属性方法给原型,这样就可以共享了
Man.prototype = People
// 注意让原型里面的constructor重新指回Man找自己的爸爸
Man.prototype.constructor = Man
const kun = new Man()
console.log(kun)

Image.png

3. 问题:

如果我们给男人添加了一个吸烟的方法,发现女人自动也添加这个方法

// 人类 公共的属性和方法
const People = {
    head: 1,
    eyes: 2,
    legs: 2,
    say: function() {},
    eat: function() {}
}
// 男人
function Man() {
}
// 把公共的属性方法给原型,这样就可以共享了
Man.prototype = People
// 注意让原型里面的constructor重新指回Man找自己的爸爸
Man.prototype.constructor = Man
// 抽烟
Man.prototype.smoking = function() {}
const kun = new Man()
console.log(kun)
// 女人
function Woman() {
    this.baby = function() {}
}
// 把公共的属性方法给原型,这样就可以共享了
Woman.prototype = People
// 注意让原型里面的constructor重新指回Woman找自己的爸爸
Woman.prototype.constructor = Woman
const ji = new Woman()
console.log(ji)

Image.png

原因

男人和女人都同时使用了同一个对象,根据引用类型的特点,他们指向同一个对象,修改一个就会都影响

Image.png

4. 解决:

需求:男人和女人不要使用同一个对象,但是不同对象里面包含相同的属性和方法

答案:构造函数

new 每次都会创建一个新的对象

// 人类 公共的属性和方法
function People() {
    this.head = 1
    this.eyes = 2
    this.legs = 2
    this.say = function() {}
    this.eat = function() {}
}
// 男人
function Man() {
}
// 把公共的属性方法给原型,这样就可以共享了
Man.prototype = new People()
// 注意让原型里面的constructor重新指回Man找自己的爸爸
Man.prototype.constructor = Man
// 抽烟
Man.prototype.smoking = function() {}
const kun = new Man()
console.log(kun)
// 女人
function Woman() {
    this.baby = function() {}
}
// 把公共的属性方法给原型,这样就可以共享了
Woman.prototype = new People()
// 注意让原型里面的constructor重新指回Woman找自己的爸爸
Woman.prototype.constructor = Woman
const ji = new Woman()
console.log(ji)

Image.png

思路

真正做这个案例,我们的思路应该是先考虑大的,后考虑小的

1. 人类共有的属性和方法有那些,然后做个构造函数,进行封装,一般公共属性写到构造函数内部,公共方法,挂载到构造函数原型身上。

2. 男人继承人类的属性和方法,之后创建自己独有的属性和方法

3. 女人同理


3. 原型链

基于原型对象的继承使得不同构造函数的原型对象关联在一起,并且这种关联的关系是一种链状的结构,我们将原型对象的链状结构关系称为原型链

Image.png

原型链-查找规则

 当访问一个对象的属性(包括方法)时,首先查找这个对象自身有没有该属性。

 如果没有就查找它的原型(也就是 __proto__指向的 prototype 原型对象

 如果还没有就查找原型对象的原型(Object的原型对象

 依此类推一直找到 Object 为止(null

 __proto__对象原型的意义就在于为对象成员查找机制提供一个方向,或者说一条路线

 可以使用 instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上




头像
0/200
图片验证码