文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

JavaScript原型链及常见的继承方法

2024-04-02 19:55

关注

原型链

原型链的概念

在JavaScript中,每一个构造函数都有一个原型,这个原型中有一个属性constructor会再次指回这个构造函数,这个构造函数所创造的实例对象,会有一个指针(也就是我们说的隐式原型__proto__或者是浏览器中显示的[[Prototype]])指向这个构造函数的原型对象。如果说该构造函数的原型对象也是由另外一个构造函数所创造的实例,那么该构造函数的原型对象也会存在一个指针指向另外一个构造函数的原型对象,周而复始,就形成了一条原型链。 最特别的是所有的没有经过再继承函数都是由Function实例化来的,所有的除了函数外的对象都是由Object实例化来的,其中Object也是由Function实例化来的,但是Object.prototype.__proto__ === null 是成立的。

再强调一遍:原型链是沿着对象的隐式原型一层层的去寻找的,找到的是构造函数所创造的实例。例如下:

这个就是相当于由Studentnew 出来的实例s,查找自身的 name 属性,然后沿着原型链查找,找到Student中的prototype当中,然后找到了name这个属性。

而这个例子,由红框框起来的代码(寄生继承的关键代码),代替注释掉的部分,最终s是找不到name属性的,这是因为红框中的代码,仅仅是将Student的隐式原型指向了Person的显示原型对象,未能创建任何的实例,当然就不会存在属性这个说法。

原型链的问题

原型链的问题主要有两个方面,第一个问题是,当原型中出现包含引用值(比如数组)的时候,所有在这条原型链中的实例会共享这个属性,造成“一发而动全身”的问题。第二个问题就是子类在实例化时,不能够给父类型的构造函数传参,即

无法在不影响所有对象实例的情况下把参数传递进父类型的构造函数传参

几种常见的继承方法

盗用构造函数

function SuperType() {
    this.friends = ['张三','李四']
}

function SubType() {
    SuperType.call(this);
}

const p1 = new SubType();
p1.friends.push('王武');

const p2 = new SubType();
console.log(p2.friends); // ['张三','李四', '王武']

盗用构造函数实现继承在这个例子中有了充分的体现: 首先在子类的构造函数中调用父类的构造函数。因为毕竟函数就是特定上下文中执行代码的简单对象,所以可以使用call()方法以创建的对象为上下文执行的构造函数。

盗用构造函数的主要问题,也是创建对象的几种方式中构造函数模式自定义类型的问题:必须在构造函数中定义方法,造成内存浪费。另外,子类也不能访问父类原型上定义的方法,因此,盗用构造函数也不会单独使用。

组合继承

组合继承也称为伪经典继承,综合了原型链和构造函数,将两者的有点结合起来。基本的思路就是使用原型链继承原型上的属性和方法,而通过盗用构造函数继承实现实例的属性。这样就可以把方法定义在原型上实现复用,又可以让每个实例有自己的属性。

function SuperType(name) {
    this.name = name;
    this.friends = ['张三','李四'];
}
SuperType.prototype.sayName = function() {
    console.log(this.name)
}
// 继承方法
SubType.prototype = new SuperType();
function SubType(name, age) {
    SuperType.call(this, name);
    this.age = age;
}
const p1 = new SubType('赵六', 12);
const p2 = new SubType('赵六2', 22);
// 创建的 p1 和 p2 能够拥有自己的属性并且引用值属性也是独立的,此外,每一个实例能够公用父类的方法。

组合继承已经接近完美了,但是,我们发现,实现组合继承就要调用两次父类构造函数。在本质上,子类型最终是要包含超类对象的所有实例属性,子类构造函数只要在执行时重写自己的原型就行了,这就为减少一次调用父类构造函数提供了思路。

原型式继承

const person = {
    name: 'zs',
    friends: ['ls','ww']
}
// 创造出一个实例,这个实例的隐式原型指向 person
const anotherPerosn = Object.create(person);
anotherPerosn.name = 'xm'
anotherPerosn.friends.push('zl')

console.log(anotherPerosn.name) // xm
console.log(anotherPerosn.friends) // ['ls','ww', 'zl'];

const anotherPerosn2 = Object.create(person);
anotherPerosn.name = 'xh'
anotherPerosn.friends.push('dd')

console.log(anotherPerosn2.name) // xh
console.log(anotherPerosn2.friends) // ['ls','ww', 'zl', 'dd'];

对于原型链继承就不再过多的解释了。。。。

寄生式继承

寄生式继承与原型式继承比较相似,都会存在属性引用值共享的问题。

function createAnotherPerson(original) {
    const clone = Object.create(original); //通过调用函数创建一个新的对象
    clone.sayHi = function() { // 以某种方式增强这个对象
        console.log('Hi');
    }
    return clone;
}

寄生式继承,不仅存在着属性引用值共享的问题而且函数还不能进行复用。

寄生组合式继承

// 实现了寄生式组合继承的核心逻辑
function inheritPrototype(subFn, parentFn){
    subFn.prototype = Object.create(parentFn.prototype); // 创建赋值对象
    Object.defineProperty(subFn.prototype,'constructor', {   // 增强对象
        enumerable: false,
        writable: false,
        configurable: false,
        value: subFn,
    })
}
function Person(name, age, address) {
    this.name = name;
    this.age = age;
    this.address = address;
}
Person.prototype.eating = function() {
        console.log(this.name + "正在吃饭");
} // 共享方法

function Student(name, age, address, sno) {
    Person.call(this, name, age, address); // 绑定 this 确保创建出来的对象是相互独立的
    this.sno = sno;
    this.studing = function() {
        console.log(`${this.name}正在学习`)
    }
}

function Teacher(name, age, address, tno) {
    Person.call(this, name, age, address)
    this.tno = tno;
}

寄生+组合式(构造函数+原型链)完美的解决了其他继承出现的问题。

到此这篇关于JavaScript原型链及常见的继承方法的文章就介绍到这了,更多相关JS原型链内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     801人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     348人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     311人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     432人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     220人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-前端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯