代码界的铁三角:构造函数、原型与实例携手改变 JavaScript 世界

192 阅读4分钟

前言:

在日常使用 JavaScript 时,难免会出现需要我们创建许多对象,在 JavaScript 中,并不缺乏创建对象的方法,比如最简单、直接的通过对象字面量来创建对象,但是却比较随意且不够灵活,那么我们随即就可以想到通过 class来批量生产对象,其不仅简洁而且封装性强,可以说是不二之选。但是,有一个致命的问题,class是在 es6 引入的,那么在 es5 中我们没有办法来实现和class 相似的、高效的创建对象的其他方法吗?那么就要请出今天的主角们---构造函数、原型与实例来助我们一臂之力。

初识铁三角

构造函数:

函数想必大家肯定不陌生,但是构造函数是什么呢?它也叫函数,那么与普通函数有什么区别吗?我们不妨来看一串代码

function Person(name,age) {
    this.name = name;
    this.age = age;
}
function add(a,b){
    return a + b;
}

const xxl = new Person("西西里",18);
const c = add(10,20);

这段代码中我们创建了两个函数Personadd,从代码格式上看我们不难发现它们包含两个差异。

  • 命名: 构造函数通常以大写字母开头,而普通函数开头通常为小写(这是编程风格,也是程序员之间默认的约定)
  • 调用: 普通函数可以直接调用,而构造函数由于包含this作为指针来指向实例化对象,所以在调用时需要用new运算符。

所以一个函数是否为构造函数,我们只需要抓住其命名与调用方式即可区分,但是这仅仅只是外观上,而内部机制就一样吗?当然不是,这里我们就需要去了解“铁三角”的另一位成员---原型。

原型:(prototype)

在JavaScript中,原型是理解对象继承和共享属性的关键概念。原型机制使得对象可以继承其他对象的属性和方法, 这是JavaScript实现面向对象编程的重要方式之一。而在原型中我们要分别介绍 原型对象原型链

原型对象(Prototype Object):

每个 JavaScript 对象都有一个内部属性 [[Prototype]],通常通过 __proto__ 属性访问。这个内部属性指向另一个对象,称为原型对象。原型对象可以包含属性和方法,这些属性和方法可以被所有继承它的对象共享。例如:

const kun = {
    name: "坤坤",
    playBasketball: function() {
        console.log(`${this.name}爱打篮球`);
    }
}
function Person(name,age) {
    this.name = name;
    this.age = age;
}

const xixi = new Person("西西里",18);
console.log(xixi.__proto__);
// Person.prototpye 指向默认原型对象->Object.prototype

Person.prototype = kun;
// Person.prototpye 指向新的原型对象->kun

const ji = new Person("鸡",19);
ji.playBasketball();
console.log(ji.__proto__);
// ji.__proto__ 指向 Person.prototype 实例对象

运行代码后我们可以得到以下结果

image.png

在上述代码中,我们创建了一个对象为kun,我们可以看到其内部包含属性name与方法playBasketball,后续我们创建了一个构造函数Person,此时我们创建对象xixi再输出Person.prototype就会发现,返还的内容是{},这是因为在未指明原型对象前,默认原型对象为Object.prototype,所以在后续我们将原型对象指向kun后,再进行创建对象后,输出Person.prototype就可以得到kun的内部属性与方法了,而且在创建新的 对象ji后我们也发现了其拥有了kun的方法。

原型链(Prototype Chain):

当我们尝试访问一个对象的属性或方法时,JavaScript 引擎会首先在该对象自身中查找。如果找不到,引擎会沿着 [[Prototype]] 链向上查找,直到找到该属性或方法,或者到达原型链的末端(通常是 Object.prototype),而这个查找过程称为原型链。例如:

function Person(name,age) {
    this.name = name;
    this.age = age;
}
Person.prototype.name = '虎哥'
Person.prototype.hometown = '山东'

let person1 = new Person('刀哥',38);
console.log(person1.name,person1.hometown);//运行结果: 刀哥 山东

Person1中包含name 属性,但是并没有hometown属性,但是在我们的原型对象中却包含hometown,那么JS 引擎就会顺着原型链查找到原型对象的hometown 并打印出来。

总结铁三角关系:

构造函数、原型对象和实例对象各司其职,却又彼此依存:

  • 构造函数:它是对象的“造物主”,负责按照特定的模版创建新的对象。
  • 原型对象:它是共享资源的“宝库”,为所有实例提供共用的属性和方法。
  • 实例对象:它是具体而微的“居民”,拥有独特的个性,但也能享受“宝库”中的资源。

5b9734cf8eaf4529f1cf246d468db6a3.jpg

---欢迎各位点赞、收藏、关注,如果觉得有收获或者需要改进的地方,希望评论在下方,不定期更新,都看到这里了,真的忍心不点个赞吗~~~

0bae-hcffhsw0416753.gif