原型与原型链

一、什么是原型

在JavaScript中,每个对象都有一个指向另一个对象的引用,叫做原型。原型是JavaScript中一个比较重要的概念。

通过使用构造函数创建的对象,会自动拥有一个原型对象。原型的作用就是用来继承属性和方法。

function Person(name, age) {
  this.name = name;
  this.age = age;
}

Person.prototype.sayHello = function() {
  console.log("Hello, " + this.name);
};

var person1 = new Person("Alice", 18);
var person2 = new Person("Bob", 20);

person1.sayHello(); // "Hello, Alice"
person2.sayHello(); // "Hello, Bob"

在这个例子中,我们定义了一个Person对象,通过Person的原型来增加了一个sayHello方法,然后我们根据这个构造函数来创建两个不同的对象person1和person2,通过调用sayHello方法,我们可以看到两个对象都可以正确的继承到sayHello方法。

二、原型链的作用

原型是可以被继承的,由此形成的继承关系被称为原型链。当对象调用方法或属性时,如果本身找不到,就会去原型对象中寻找,如果还是找不到,则会继续去原型对象的原型对象中查找,构成一个链式结构,直到最后查找完整个链才会返回undefined。

function Animal() {
  this.name = "Animal";
}

Animal.prototype.eat = function() {
  console.log(this.name + " is eating");
};

function Cat() {
  this.name = "Cat";
}

Cat.prototype = new Animal();
Cat.prototype.constructor = Cat;

var cat1 = new Cat();
cat1.eat(); // "Cat is eating"

在这个例子中,我们定义了一个Animal构造函数,然后在它的原型上添加一个eat方法。然后我们又定义了一个Cat构造函数,由于我们希望Cat继承Animal的属性和方法,所以我们将Cat的原型指向了Animal的实例,这样一来Cat就可以调用到Animal的属性和方法了。

当我们调用cat1的eat方法时,首先在cat1对象上寻找是否有eat属性或方法,没有找到,于是它会去cat1的原型对象Cat.prototype中查找,还是没有找到,于是它又去Cat.prototype的原型对象Animal.prototype中查找,最终在Animal.prototype中找到了eat方法,然后执行。这就是原型链的查找过程。

三、原型链的细节

在JavaScript中,有些方法是自身属性,有些是继承属性;也有一些属性是自身的,有一些是继承来的。由于原型链的继承关系,有些情况下会出现一些意料之外的结果,下面举几个例子说明一下:

var str = "hello";
console.log(str.toString()); // "hello"

var arr = [1,2,3];
console.log(arr.toString()); // "1,2,3"

在这两个例子中,我们在字符串和数组对象上调用了toString方法,然而这两个对象并没有自己的toString方法,是从它们的构造函数Object中继承了toString方法。这也是为什么其他对象也可以使用toString方法。

function Person(name, age) {
  this.name = name;
  this.age = age;
}

Person.prototype.sayHello = function() {
  console.log("Hello, " + this.name);
};

var person1 = new Person("Alice", 18);
var person2 = new Person("Bob", 20);

console.log("name" in person1); // true
console.log(person1.hasOwnProperty("name")); // true
console.log(person1.hasOwnProperty("sayHello")); // false 

console.log("sayHello" in person1); // true
console.log(person1.__proto__.hasOwnProperty("sayHello")); // true
console.log(person1.__proto__.hasOwnProperty("name")); // false

在这个例子中,我们通过person1对象来演示hasOwnProperty方法和in方法的区别。hasOwnProperty是检测对象自身是否拥有某个属性,而in方法是检测对象是否拥有某个属性,不管是自身还是继承而来的。因为person1对象自己拥有name属性,所以hasOwnProperty返回true,而因为sayHello方法是从它的原型对象Person.prototype上继承而来的,所以hasOwnProperty返回false,in方法却返回true。

四、如何组合使用原型与构造函数

在实际编程中,常常需要使用原型和构造函数来一起工作。比如,希望继承某个对象,并在继承的同时传递一些参数;或者希望封装私有变量,但又能让实例对象共享某些公共的属性和方法等等。以下给出一些例子:

// 1、通过原型继承属性和方法,通过构造函数来传递参数
function Person(name, age) {
  this.name = name;
  this.age = age;
}

Person.prototype.sayHello = function() {
  console.log("Hello, " + this.name);
};

function Student(name, age, school) {
  Person.call(this, name, age);
  this.school = school;
}

Student.prototype = new Person();
Student.prototype.constructor = Student;

Student.prototype.sayHello = function() {
  console.log("Hello, I'm a student, my name is " + this.name);
};

var student1 = new Student("Alice", 18, "Harvard");
student1.sayHello(); // "Hello, I'm a student, my name is Alice"

// 2、使用原型来封装私有变量
function Counter() {
  var count = 0;
  this.getCount = function() {
    return count;
  };
}

Counter.prototype.increment = function() {
  var count = this.getCount();
  count++;
  this.getCount = function() {
    return count;
  };
};

var counter1 = new Counter();
counter1.increment();
console.log(counter1.getCount()); // 1

var counter2 = new Counter();
counter2.increment();
console.log(counter2.getCount()); // 1,而不是2

以上这两个例子都非常常见。第一个例子通过Student构造函数来传递参数,同时继承了Person的属性和方法;第二个例子封装了私有变量,并通过原型来共享increment方法。

五、总结

原型和原型链是JavaScript中比较重要的概念,通过灵活运用原型和构造函数,我们可以很方便地实现继承、私有变量等功能。同时,需要注意的是,由于原型链的存在,有些方法可能并不是对象自身的,而是继承而来的,因此在编程时需要特别注意。

原创文章,作者:GNIGG,如若转载,请注明出处:https://www.506064.com/n/360768.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
GNIGGGNIGG
上一篇 2025-02-24 00:33
下一篇 2025-02-24 00:33

相关推荐

  • 谷歌Axure插件——提高原型设计效率的利器

    一、快速制作自定义组件 1、Axure自带的组件库虽然丰富,但在某些情况下我们需要自己设计一些特殊的组件,而谷歌Axure插件提供了一个轻松快捷的方式。 以设计一个自定义开关组件为…

    编程 2025-04-22
  • 反思原型链

    一、原型链基础 JavaScript的原型链是一种从对象到另一个对象的委托关系。它在一个对象的属性找不到时,会沿着原型链往上找指定名称的属性或方法。我们来看一个例子: functi…

    编程 2025-04-12
  • 深入解析JavaScript原型链面试题

    JavaScript 是一种弱类型、基于原型的编程语言。原型是 JavaScript 的一项非常重要的特性,也是面试中经常考察的知识点。JS 原型链是基于原型的面向对象编程的基石,…

    编程 2025-03-12
  • 原型模式的应用场景

    一、单例模式的应用场景 单例模式是一种常见的设计模式,其应用场景也非常广泛。单例模式通常只允许一个实例存在,可以用于创建全局唯一的对象。在使用原型模式实现单例模式时,先创建一个原型…

    编程 2025-02-17
  • js原型链编程,js原型链概念

    本文目录一览: 1、javascript 原型,原型链是什么?有什么特点 2、js原型和原型链的理解是什么? 3、js原型链和继承的理解 4、谈谈对原型链的理解 JS原型链怎么理解…

    编程 2025-01-09
  • java桌面应用程序原型,软件开发 原型

    本文目录一览: 1、Java原型模式 2、Java适合开发桌面应用程序吗? 3、JAVA 怎么把程序做成 桌面应用程序 Java原型模式 不用例子,如果你的某个类在整个工程中只需要…

    编程 2024-12-15
  • 原型网络:从概念到应用

    一、什么是原型网络 原型网络(Prototypical Network)是一种深度学习中用于学习表示空间的神经网络,由于能够处理较小的数据集而被广泛应用于图像分类、目标识别等领域。…

    编程 2024-12-12
  • 软件原型设计详解

    一、软件原型设计工具 软件原型设计是实现产品设计的重要步骤,而软件原型设计工具就是我们能够使用的工具。 目前市面上存在很多软件原型设计工具,比较常见的有: Axure RP Ske…

    编程 2024-11-25
  • c语言中c=a\u003e3,C语言中,函数可以用原型说明,也可用简单说明

    本文目录一览: 1、c语言中 c=”a”是什么意思 2、在c语言中char choose=0是什么意思 3、C语言中 c=’a’, …

    编程 2024-11-08
  • c语言strcmp原型,c语言strcpy函数原型

    本文目录一览: 1、strcmp原理 2、C语言中strcmp函数怎么用啊 3、C语言编程strcmp函数的问题 4、C语言 strcmp(“how”,&#…

    编程 2024-11-05

发表回复

登录后才能评论