【每日一个知识点二】原型链

我都是想到啥写啥,丝毫没有规律。前面聊到箭头函数没有原型,就想到了再整理一篇原型链的。

原型

原型是JavaScript中对象的一个属性,它指向另一个对象,用于实现继承关系。每个对象都有一个原型属性__proto__,它指向它的原型对象。

隐式原型

在JavaScript中,每个对象(引用类型)都有一个原型属性 __proto__,也称为隐式原型。隐式原型指向创建该对象的构造函数的原型对象。当我们访问一个对象的属性或方法时,如果对象不存在该属性或方法,JavaScript会通过隐式原型链向上查找。

显式原型

每个函数对象都有一个属性 prototype,也称为显式原型。显式原型是一个普通的对象,它被用作创建新对象的原型。当我们使用 new 关键字来调用一个函数对象时,会创建一个新的对象,并将新对象的隐式原型指向函数对象的显式原型

举个例子,我们定义一个构造函数 Person,并在其原型对象上添加一个方法 sayHello

function Person(name) {this.name = name;
}Person.prototype.sayHello = function() {console.log(`Hello, my name is ${this.name}`);
};var person = new Person("Alice");
person.sayHello();  // 输出 "Hello, my name is Alice"

我们创建了一个 Person 对象,并调用了 sayHello 方法。当我们创建 person 对象时,它的隐式原型指向 Person 对象的原型对象(即 Person.prototype)。因此,person 对象可以访问和调用 sayHello 方法。

简而言之,隐式原型指向对象的构造函数的原型对象,而显式原型指向函数对象的原型对象。

原型的作用

在JavaScript中,原型主要用于实现对象的属性和方法的继承。通过原型,我们可以将一些通用的属性和方法定义在原型对象中,从而实现多个对象共享这些属性和方法的目的。

一般情况下,我们在以下场景会需要用到原型:

  1. 提高性能:原型对象中的方法是可以被所有实例共享的,而不是每个实例都重新创建一次方法。这样可以减少内存占用,提高性能。

  2. 实现继承:通过原型链的机制,我们可以实现对象之间的继承关系。子对象的原型对象可以指向父对象,从而继承父对象的属性和方法。

  3. 扩展对象:通过原型,我们可以动态地给一个对象添加属性和方法。这样可以在不修改对象本身的情况下,给对象增加新的功能。

举个例子,当处理日期和时间的时候,我们经常会使用Date对象进行操作。但是Date对象提供的方法并不总是满足我们的需求,此时我们可以利用原型来扩展Date对象的功能。

例如,我们想要获取当前日期是一周中的第几天。Date对象本身没有提供这样的方法,但我们可以通过修改Date对象的原型来添加该功能:

Date.prototype.getWeekday = function() {var weekdays = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];return weekdays[this.getDay()];
};var currentDate = new Date();
console.log(currentDate.getWeekday());  // 输出当天是星期几

在这个例子中,我们通过修改Date对象的原型,在原型上添加了一个getWeekday方法。这个方法将返回当前日期对应的星期几。这样,我们就可以通过任何一个Date对象上调用getWeekday方法,得到对应的结果。

原型链

JavaScript 规定,所有对象都有自己的原型对象(prototype)。一方面,任何一个对象,都可以充当其他对象的原型;另一方面,由于原型对象也是对象,所以它也有自己的原型。因此,就会形成一个“原型链”(prototype chain):对象到原型,再到原型的原型……

如果一层层地上溯,所有对象的原型最终都可以上溯到Object.prototype,即Object构造函数的prototype属性。也就是说,所有对象都继承了Object.prototype的属性。这就是所有对象都有valueOf和toString方法的原因,因为这是从Object.prototype继承的。

那么,Object.prototype对象有没有它的原型呢?回答是Object.prototype的原型是null。null没有任何属性和方法,也没有自己的原型。因此,原型链的尽头就是null。

Object.getPrototypeOf(Object.prototype)  // null

原型链的作用

  1. 实现属性和方法的继承:原型链使得对象可以继承其原型对象上的属性和方法,避免了重复定义和维护相同的代码。
  2. 共享属性和方法:原型对象上的属性和方法可以被多个对象共享,节省了内存空间。
  3. 动态性:在原型链上添加、修改或删除属性和方法,会影响到所有继承了该原型链的对象,可以方便地对所有对象进行统一的修改。

举例

一个常见的业务场景是创建一个基础的对象,然后通过原型链继承该对象来创建更特定的对象,以实现代码的重用和简化。

假设我们在一个电商网站中,有多种类型的商品,如衣服、鞋子和电子产品等。每个商品都有一些共同的属性,比如名称、价格和库存,同时也有一些特定的属性。

我们可以创建一个基础的商品对象 Product,它包含共同的属性和方法,比如价格计算和库存更新。然后,我们通过原型链继承 Product 来创建不同类型的商品对象,每个对象额外拥有自己特定的属性和方法。

// 基础的商品对象
var Product = {name: "",price: 0,stock: 0,calculatePrice: function() {// 计算价格的逻辑return this.price * this.stock;},updateStock: function(quantity) {// 更新库存的逻辑this.stock += quantity;}
};// 衣服对象
var Clothes = Object.create(Product);
Clothes.brand = "";
Clothes.size = "";// 鞋子对象
var Shoes = Object.create(Product);
Shoes.color = "";
Shoes.style = "";// 电子产品对象
var Electronics = Object.create(Product);
Electronics.type = "";
Electronics.warranty = "";// 使用示例
var tShirt = Object.create(Clothes);
tShirt.name = "T-Shirt";
tShirt.price = 20;
tShirt.stock = 100;
tShirt.brand = "Nike";
tShirt.size = "M";console.log(tShirt.calculatePrice());  // 输出 2000tShirt.updateStock(-10);
console.log(tShirt.stock);  // 输出 90

在这个例子中,我们通过原型链实现了商品对象的继承。基础的 Product 对象定义了共同的属性和方法,然后通过 Object.create() 方法基于 Product 对象创建了衣服、鞋子和电子产品等不同类型的对象。每个对象都可以设置自己特定的属性,同时也可以调用来自 Product 对象的共享方法。

通过原型链继承,我们可以减少重复的代码,实现代码的重用和简化。同时,当 Product 对象的属性或方法需要修改时,只需要在原型对象上进行修改,继承了该原型链的所有对象都会受到影响。这样可以确保代码的一致性和易维护性。

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

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

相关文章

hypery 十一、命令行

教程:Hyperf symfony/console composer地址: symfony/console - Packagist github地址:GitHub - symfony/console: Eases the creation of beautiful and testable command line interfaces hyperf/command github地址:https://github.com/…

Ubuntu18.04未安装Qt报qt.qpa.plugin could not load the Qt platform plugin xcb问题的解决方法

在Ubuntu 18.04开发机上安装了Qt 5.14.2,当将其可执行程序拷贝到另一台未安装Qt的Ubuntu 18.04上报错:拷贝可执行程序前,使用ldd将此执行程序依赖的动态库也一起拷贝过去,包括Qt5.14.2/5.14.2/gcc_64/plugins目录系的platforms目录…

【UE5 多人联机教程】05-生成玩家

步骤 1. 新建一个游戏模式基础 命名为“GM_Lobby” 2. 新建一个玩家控制器,命名为“PC_Lobby” 3. 新建一个游戏状态基础 命名为“GS_Lobby” 重新设置游戏模式重载、玩家控制器类、游戏状态类 4. 新建一个控件蓝图,命名为“UMG_Lobby” 打开“UMG_Lobb…

达闼面试(部分)(未完全解析)

grpc怎么解决负载均衡问题? Answer by newBing : gRPC提供了多种负载均衡策略,包括轮询、随机、最少连接数等。gRPC客户端可以使用这些策略来选择要连接的服务器。 k8s环境下部署grpc的几种方案 : 在k8s环境中,可以选择headless service,或者…

通过wait和notify来协调线程执行顺序

为什么要协调线程执行顺序 wait和notify是多线程编程中的重要工具,多线程调度是随机的,很多时候希望多个线程能够按照我们规定的顺序来执行,完成线程之间的配合工作 注意事项 1.要想让notify能够顺利唤醒wait,就需要确保wait和no…

PostgreSQL-视图-03-查询对象依赖关系视图-dba_dependencies

PostgreSQL查询对象依赖关系视图 -- PostgreSQL查询对象依赖关系视图drop view if exists tzq.dba_dependencies; create view tzq.dba_dependencies as with source_obj as (select sp.oid,sp.proname,unnest(string_to_array(regexp_replace(regexp_replace(lower(sp.prosrc…

Spring Alibaba Sentinel实现集群限流demo

1.背景 1.什么是单机限流? 小伙伴们或许遇到过下图这样的限流配置 又或者是这样的Nacos动态配置限流规则: 以上这些是什么限流?没错,就是单机限流,那么单机限流有什么弊端呢? 假设我们集群部署3台机器&a…

Vue过度与动画

Test.vue:元素外面包一层transition&#xff0c;展示的时候就默认调用style里面的v-enter-action和v-leave-action执行进入和退出效果&#xff0c;appear上来默认展示动画效果 <template><div><button click"isShow !isShow">显示/隐藏</butto…

如何高效地查询IP归属地

高效识别IP归属地是网络安全领域中的一项重要工作。准确地识别IP的归属地不仅可以帮助网络管理员追踪和定位潜在的网络攻击者&#xff0c;还可以用于网络流量分析、地理定位服务等方面。 以下将介绍几种高效识别IP归属地的方法。 使用IP归属地数据库 IP归属地数据库是一种存储…

FileNotFoundException:xxx(系统找不到指定的路径)

目录 前言 背景 解决方法 错误示例 前言 这次是有个两年前的项目吧&#xff0c;不知道为什么无法启动了。中间迭代了多个版本&#xff0c;现在另一个同事接手了&#xff0c;领导让看一下。因为时间间隔过长&#xff0c;问题处理比较费劲。其中有的是配置问题&#xff0c;比…

MySQL - 常用的命令

当涉及到具体的数据库操作时&#xff0c;我会给出实际的示例&#xff0c;以更清楚地说明每个命令的用法。 创建数据库&#xff1a; CREATE DATABASE students;列出数据库&#xff1a; SHOW DATABASES;使用数据库&#xff1a; USE students;创建表&#xff1a; CREATE TABL…

java篇 类的进阶0x06:可见性修饰符(访问修饰符)

文章目录 可见性修饰符&#xff08;访问修饰符&#xff09;成员变量都应该是 private构造方法可以是 private 的public 修饰的东西尽量不要改动非 public 的类&#xff0c;类名可以不和文件名相同protected 继承专属的访问控制 可见性修饰符&#xff08;访问修饰符&#xff09;…

学习笔记21 list

一、概述 有两种不同的方法来实现List接口。ArrayList类使用基于连续内存分配的实现&#xff0c;而LinkedList实现基于linked allocation。 list接口提供了一些方法&#xff1a; 二、The ArrayList and LinkedList Classes 1.构造方法 这两个类有相似的构造方法&#xff1a…

AVKit 播放

文章目录 - (void)testAVKit{NSString *fileName = @"ElephantSeals.mov";NSURL *fileURL = [[NSBundle mainBundle] URLForResource:fileNamewithExtension:nil]

Redis学习路线(2)—— Redis的数据结构

一、Redis的数据结构 Redis是一个Key-Value的数据库&#xff0c;key一般是String类型&#xff0c;不过Value的类型却有很多&#xff1a; String&#xff1a; Hello WorldHash&#xff1a; {name: "jack", age: 21}List&#xff1a; [A -> B -> C -> C]Set…

Unity进阶--物品,背包,角色管理器

文章目录 物品管理器背包管理器角色管理器 物品管理器 物品数据 Item.json&#xff08;json部分)&#xff08;Resources/Data/Item&#xff09; [{ "id": 1, "name": "新手剑", "des": "这是一把宝剑", "price": …

React的hooks---useLayoutEffect

useLayoutEffect 与 useEffect 类似&#xff0c;与 useEffect 在浏览器 layout 和 painting 完成后异步执行 effect 不同的是&#xff0c;它会在浏览器布局 layout 之后&#xff0c;painting 之前同步执行 effect useLayoutEffect 的执行时机对比如下&#xff1a; import Rea…

Spring Security OAuth2.0 - 学习笔记

一、OAuth基本概念 1、什么是OAuth2.0 OAuth2.0是一个开放标准&#xff0c;允许用户授权第三方应用程序访问他们存储在另外的服务提供者上的信息&#xff0c;而不需要将用户和密码提供给第三方应用或分享数据的所有内容。 2、四种认证方式 1&#xff09;授权码模式 2&#x…

CHI中的网络层

System address map □ 系统中每个Requester(包括RN和HN)必须有一个System Address Map(SAM)来决定一个request的target ID&#xff1b; □ SAM的范围可能只是简单的为所有发送的requests提供一个固定的node ID □ SAM具体的结构和格式是由具体实现决定的 □ SAM必须可以对全地…

kotlin高阶函数

kotlin高阶函数 函数式API:一个函数的入参数为Lambda表达式的函数就是函数式api 例子: public inline fun <T> Iterable<T>.filter(predicate: (T) -> Boolean): List<T> {return filterTo(ArrayList<T>(), predicate) }上面这段函数: 首先这个函…