【 js编程】原型和原型链

news/2024/11/7 0:45:14/文章来源:https://www.cnblogs.com/o-O-oO/p/18531330

原创 mike Web全栈开发者驿站

原型和原型链在 js中起着至关重要的作用。它们使得 js 能够以一种独特的方式实现面向对象编程,虽然与传统的面向对象编程语言有所不同,但却提供了很大的灵活性和强大的功能。然而,原型链也有一些缺点,如属性查找的性能问题、继承的脆弱性以及隐私和封装问题等,在使用时需要注意这些问题,以确保代码的正确性和可维护性。

一、什么是原型

定义:每个函数都有一个 prototype 属性,它指向一个对象,这个对象被称为该函数的原型。当函数被用作构造函数创建对象时,新创建的对象会自动拥有一个指向构造函数原型的内部指针,这个指针被称为对象的原型。

function Person() {}console.log(Person.prototype);

原型的作用

实现属性和方法的共享:在原型上定义的属性和方法可以被由该构造函数创建的所有对象共享。这可以节省内存空间,因为不需要为每个对象都单独存储相同的属性和方法。

function Person() {}Person.prototype.name = '无名氏';Person.prototype.sayHello = function() {console.log('Hello!');};const person1 = new Person();const person2 = new Person();console.log(person1.name); // 无名氏console.log(person2.name); // 无名氏person1.sayHello(); // Hello!person2.sayHello(); // Hello!

二、什么是原型链

定义:当访问一个对象的属性或方法时,如果在对象本身找不到,JavaScript 引擎会沿着对象的原型链向上查找,直到找到该属性或方法或者到达原型链的顶端(Object.prototype)。对象的原型链是由对象的原型以及原型的原型等组成的链条。


function Person() {}Person.prototype.name = '无名氏';const person1 = new Person();console.log(person1.name); // 无名氏

在这个例子中,当访问 person1.name 时,首先在 person1 对象本身查找 name 属性,找不到后沿着原型链在 Person 的原型上找到了 name 属性。

原型链的作用

实现继承:JavaScript 中没有传统的类继承概念,而是通过原型链实现继承。一个对象可以通过原型链继承另一个对象的属性和方法。

 function Person() {}Person.prototype.sayHello = function() {console.log('Hello from Person!');};function Student() {}Student.prototype = Object.create(Person.prototype);const student1 = new Student();student1.sayHello(); // Hello from Person!

在这个例子中,Student 的原型被设置为一个新的对象,这个新对象的原型是 Person.prototype,从而实现了 Student 对象继承 Person 对象的方法。

原型决定实例的初始属性和方法

当使用构造函数创建一个实例时,该实例会自动拥有一个指向构造函数原型的内部指针。构造函数的原型上定义的属性和方法会被实例所继承,成为实例的初始属性和方法。

function Person() {}
Person.prototype.name = '无名氏';
Person.prototype.sayHello = function() {console.log('Hello!');
};
const person1 = new Person();
console.log(person1.name); // 无名氏
person1.sayHello(); // Hello!

在这个例子中,构造函数 Person 的原型上定义了属性 name 和方法 sayHello。当创建实例 person1 时,person1 自动继承了这些属性和方法。

实例可以修改从原型继承的属性

实例可以修改从原型继承的属性值,但这不会影响原型上的属性值。如果实例添加了一个与原型上同名的属性,那么实例会优先使用自己的属性,而不是原型上的属性。

function Person() {}
Person.prototype.name = '无名氏';
const person1 = new Person();
const person2 = new Person();
console.log(person1.name); // 无名氏
console.log(person2.name); // 无名氏
person1.name = '张三';
console.log(person1.name); // 张三
console.log(person2.name); // 无名氏

在这个例子中,修改 person1 的 name 属性不会影响 person2 的 name 属性,因为 person1 只是在自己的实例上添加了一个新的属性,而不是修改了原型上的属性。

实例可以添加自己独有的属性和方法

除了继承原型上的属性和方法,实例还可以添加自己独有的属性和方法。这些属性和方法不会影响其他实例或原型

function Person() {}
const person1 = new Person();
person1.age = 20;
person1.sayAge = function() {console.log(`I am ${this.age} years old.`);
};
console.log(person1.age); // 20
person1.sayAge(); // I am 20 years old.
const person2 = new Person();
console.log(person2.age); // undefined
person2.sayAge(); // TypeError: person2.sayAge is not a function

在这个例子中,person1 添加了自己独有的属性 age 和方法 sayAge,而 person2 没有这些属性和方法。

三、如何确定一个对象的原型?

可以通过以下几种方式确定一个对象的原型:

使用Object.getPrototypeOf()方法

这是最直接的方法,它返回指定对象的原型(即内部的 [[Prototype]])。

function Person() {}
const person = new Person();
const prototype = Object.getPrototypeOf(person);
console.log(prototype === Person.prototype); // true

使用__proto__属性(不推荐在生产环境中使用)

在一些浏览器环境中,对象有一个 __proto__ 属性,可以用来访问对象的原型。但这个属性是非标准的,不建议在生产环境中使用。


function Person() {}
const person = new Person();
console.log(person.__proto__ === Person.prototype); // true

通过构造函数的prototype属性推断

如果知道一个对象是由哪个构造函数创建的,可以通过该构造函数的 prototype 属性来推断对象的原型。

function Person() {}
const person = new Person();
console.log(person instanceof Person && Person.prototype.isPrototypeOf(perso
n)); // true

这个方法通过判断对象是否是构造函数的实例以及构造函数的原型是否在对象的原型链上来间接确定对象的原型。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/827957.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

全网最适合入门的面向对象编程教程:58 Python字符串与序列化-序列化Web对象的定义与实现

如果我们要在不同的编程语言之间传递对象,就必须把对象序列化为标准格式,比如XML\YAML\JSON格式这种序列化Web对象。这种序列化Web对象容易与其他程序设计语言交互,可读性强,容易被传递给其它系统或客户端。全网最适合入门的面向对象编程教程:58 Python 字符串与序列化-序…

开源低代码平台-Microi吾码-源码本地运行-后端

开源低代码平台-Microi吾码-简介技术框架:.NET8 + Redis + MySql/SqlServer/Oracle + Vue2/3 + Element-UI/Element-Plus 平台始于2014年(基于Avalon.js),2018年使用Vue重构,于2024年10月29日开源 试用地址:https://microi.net Gitee开源地址:https://gitee.com/ITdos/m…

CAPL基础

CAPL基础 1.CAPL如何生效 CAPL通过在Simulation Setup窗口设置CAPL节点,并加载对应的CAPL文件使CAPL生效。 2.Event驱动 CAPL语言的运行逻辑是事件触发,当满足条件时执行对应的代码 如下图所示有启动触发、停止触发、发送报文触发、定时器触发和按键触发等3.报文发送 1.自定义…

开源 - Ideal库 - 常用时间转换扩展方法(一)

分享《开源-Ideal库》系列文章,含公共、文档等库封装,首篇介绍时间转换封装,包括日期时间、时间戳与字符串间转换方法,后续上传至Nuget,测试代码已上传至代码库。从事软件开发这么多年,平时也积累了一些方便自己快速开发的帮助类,一直在想着以什么方式分享出来,因此有了…

excel排序

目录Excel成绩排名的两种方法方法一:先排序,再填排名 Excel成绩排名的两种方法 方法一:先排序,再填排名 具体步骤如下:先左键选中要排序的区域,如下图右键,然后选择排序->自定义排序选择要排序的区域(注意勾选数据包含标题)​ 数据包含标题的意思就是,上面的姓名、…

千锋Linux云计算-文件权限管理

掌握基本权限ugo的命令(chmod、chown),列举2条设置权限命令并解释每个单词含义。 掌握基本权限acl的命令(setfacl、getfacl),列举2条设置权限命令并解释每个单词含义。 了解特殊权限含义(suid、chattr、umask),列举2条设置权限命令并解释每个单词含义。1. 设置传统权…

静态路由规则配置

静态路由配置 本质上通过配置虚拟机实现不同网段之间进行通信 第一步:准备3台虚拟机第一台网卡配置NAT模式;第二台配置两个网卡,分别为配置NAT模式 + LAN区段;第三台配置LAN区段第二步:配置网卡相关信息先查看宿主机(物理机)VMnet8网卡的IP和子网掩码配置网卡相关信息【…

SpringBoot获取文件将要上传的IP地址

SpringBoot获取文件将要上传的IP地址说明: 有的项目会涉及文件上传,比如“更换logo业务”,或者“自定义任务上传脚本等业务”都会涉及上传,而有的项目上传成功后找不到上传地址,所以需要打印IP,方便用户知晓上传的精确地址,下面封装了一个IPv4 工具类(因为是拷贝现成代…

Linux 下搭建 Spark3 + Jupyter 环境

spark3 + pyspark + jupyter 环境搭建最近想着来玩一玩大数据, 前段时间集中过了一遍 java, 最近又看了一些基础的 scala, 我感觉吧, 我都不想学. 还是觉得用 sql, javascript, python 这种脚本语言操作起来顺手, 但这并不影响对这个大数据生态的理解和学习. 这里主要是来记录一…

LeetCode3264[K次乘运算后的最终数组I]

LeetCode3264[K次乘运算后的最终数组I]题目 链接 LeetCode3264[K次乘运算后的最终数组I] 详情实例 实例1实例2提示题解 思路 先找到最小值 然后对最小值进行操作 最后输出容器 代码 class Solution { public:int findVecMinNumIndex(vector<int> nums)//找出最小值的下标…

SpringCloudGateway网关服务实现文件上传功能

SpringCloudGateway网关服务实现文件上传功能@目录说明SpringBoot和SpringCloudGateway项目区别说明1.SpringBoot的成功案例文件上传代码pom前端代吗Controller代码 重点在:@RequestParam("file00") MultipartFile file2.SpringCloudGateway的成功案例文件上传代码C…

React.memo vs. useMemo: Major differences and use cases

from: https://blog.logrocket.com/react-memo-vs-usememo/Memoization is one of the ways to optimize performance. In this article, we’ll explore how it works in React. What is memoization? In simple terms, memoization is a process that allows us to cache …