Javascript原型链详解,一文带你彻底搞懂js原型、原型对象及原型链

一、原型链简介

当谈到 JavaScript 中的原型链时,我们需要先理解几个关键概念:构造函数、原型、原型对象和原型链。

1. 构造函数:在 JavaScript 中,构造函数是用于创建对象的函数。当使用 `new` 关键字调用构造函数时,会创建一个新对象,并将该对象的原型指向构造函数的原型对象。

2. 原型对象:每个 JavaScript 对象都有一个原型对象,它包含该对象的方法和属性。原型对象可以被共享,即多个对象可以共享同一个原型对象。

3. 原型链:原型链是一种机制,用于实现对象之间的继承关系。当访问一个对象的属性或方法时,如果该对象本身没有这个属性或方法,JavaScript 引擎会沿着原型链向上查找,直到找到对应的属性或方法或者到达原型链的顶端(即 `Object.prototype`)。 通过原型链,JavaScript 实现了基于原型的继承机制,这使得对象之间可以共享属性和方法,同时也保留了各自的特定属性和方法。

下图是对原型链的简单示意:

 原型链:

 二、原型对象

如上图所示,在js中,每一个实例对象都有一个__proto__属性指向自己的原型对象,而这个原型对象也会有一个__proto__属性指向自己的原型对象,这样一直往后重复,直到Object的原型对象为null停止,这就是原型链。我们可以用构造函数的方式来创建一个对象来验证,我们用Obj构造函数构造Obj对象,然后往上查看这个对象的__proto__属性。

//构造函数
let Obj = function(name) {
    this.name = name
}

//利用构造函数创建对象
let obj = new Obj('test')

//获取对象的原型对象
let a = obj.__proto__

//再获取该对象的原型对象 b的雷响为Object
let b = a.__proto__

//再获取原型对象,c为null原型链终止
let c = b.__proto__

 在上述代码中,对象obj的原型对象的原型对象为Object,而Object的原型对象为null。如下图所示。

三、构造函数 

 讲完原型对象,就不得不说说构造函数。构造函数对象有一个prototype属性,其指向的对象和该构造函数构造的实例对象的__proto__属性指向的是同一个对象(原型对象)。接着上面的例子,我们比较一下Obj(构造函数)的prototype和obj(实例对象)的__proto__属性,最后发现这两个属性指向的是同一个对象。

obj.__proto__ === Obj.prototype  //true

在描述原型链的图中,也提到过,对象的原型对象的constructor属性指向对象的构造函数,我们也可以用代码验证

obj.__proto__.constructor === Obj //true

至此整个原型链的描述结束,为了更加深入的理解js的原型链和构造函数的关系,这里我们可以自己简单实现一下new关键字。

//第一个参数为构造函数,可变参数为构造函数的参数
let myNew = function(Constructor, ...args) {

    //用Object的create方法来构造Constructor指向的原型对象
    let tmp = Object.create(Constructor.prototype);

    //创建一个对象,将其this指针指向tmp(即作为该对象的原型对象)
    let res = Constructor.call(tmp, ...args);

    //判断res对象是否是object是就直接返回,否则返回tmp
    if (typeof res === 'object') return res;
    else return tmp;
}

接着我们用myNew来创建Obj对象,并验证与new创建的Obj对象是否是同一个类。

let obj2 = myNew(Obj, 'obj2')

obj2.__proto__ === obj.__proto__  //true

obj.__proto__ === Obj.prototype  //true

结果正确。

四、原型链的作用

原型链的一大作用是通过原型对象为对象增加方法,例如我们可以通过原型对象来为obj添加talk方法。

obj.__proto__.talk = function() {
    console.log(this.name);
}

obj.talk() //输出test

obj2.talk() //输出obj2

还有一大作用即通过原型链来实现继承,例如

//父类构造函数
function Animal(name) {
    this.name = name;
}

//为父类增加方法
Animal.prototype.sayName = function() {
    console.log("My name is " + this.name);
};

//子类构造函数
function Dog(name, breed) {
    Animal.call(this, name); //将当前上下文this绑定到Animal的构造函数上
    this.breed = breed;
}

Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;

Dog.prototype.bark = function() {
    console.log("Woof! Woof!");
};

let myDog = new Dog("Buddy", "Golden Retriever");
myDog.sayName(); // 输出:My name is Buddy
myDog.bark(); // 输出:Woof! Woof!

 

五、总结 

原型链是 JavaScript 中的一个重要特性,它是实现对象之间继承关系的机制。在 JavaScript 中,每个对象都有一个原型(prototype)属性,指向另一个对象。当试图访问一个对象的属性或方法时,如果该对象本身没有这个属性或方法,JavaScript 引擎会沿着原型链向上查找,直到找到对应的属性或方法为止

  • 12
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值