面试官:聊聊js原型

news2024/10/5 19:21:39

一分钟了解原型对象

js分为函数对象和普通对象 ,每个对象都有__proto__属性,但是只有函数对象才有prototype属性,prototype属性就是函数的原型对象。

比如说 构造函数通过new 实化一个实例对象,实例对象的__proto__ 指向原型对象 ,同时构造函数prototype也指向原型对象。

比如:

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

Person.prototype.sayHello = function() {
  console.log("Hello, my name is " + this.name + " and I am " + this.age + " years old.");
}

var person1 = new Person("Alice", 25);
var person2 = new Person("Bob", 30);

person1.sayHello(); // 输出:Hello, my name is Alice and I am 25 years old.
person2.sayHello(); // 输出:Hello, my name is Bob and I am 30 years old.

Person是一个函数,也是构造函数,他的prototype就是指向原型对象。我们使用 Person.prototype 对象来为每个 Person 对象定义了一个共同的方法 sayHello。这个方法输出了一个字符串,表示人物的名字和年龄。

我们使用 new 关键字来创建了两个 Person 对象,并且分别调用了 sayHello 方法,输出了不同的字符串。这是因为 person1 和 person2 都继承了 Person.prototype 对象上的 sayHello 方法,但是它们的属性值是不同的。

原型对象到底是什么?

可以将原型对象比做是一个模板,这个模板包含了一些常用属性和方法,然后我们可以用它来创建新的对象。就像是我们可以用一个模板来快速制作许多同样的产品一样,每个产品的具体细节可能不同,但是它们的基本结构和特征都是相同的。

比如说,我们可以有一个“车”的原型对象,它包含了一些常用的属性和方法,比如车型、品牌、最高时速、加速度等等。然后我们可以用这个原型对象来创建许多不同的车型,如轿车、卡车、摩托车等等。由于这些车型都基于同一个原型对象创建,因此它们都具有相同的基本特征和结构,但是具体的细节可能略有不同,比如轿车和卡车的尺寸、载重等等。

同样地,在JavaScript中,我们可以使用原型对象来快速创建多个对象,并且这些对象都具有相同的基本特征和方法。这种基于原型对象的方式可以实现代码的重用,提高开发效率。

原型对象能干什么

上面的例子已经说明,我们可以在函数的prototype熟悉,也就是原型对象上添加熟悉和方法,这些都会被将来根据这个函数new出来的对象继承。

原型对象在JavaScript中有着重要的作用,常常用于以下几个方面:

实现继承:通过原型对象,我们可以创建新的对象,并且继承原型对象上的属性和方法。这种基于原型的继承方式可以让我们更方便地实现面向对象编程。

共享属性和方法:通过将属性和方法定义在原型对象上,我们可以让多个对象共享这些属性和方法。这样可以减少内存占用,提高代码的效率。

扩展对象:通过修改原型对象,我们可以在运行时扩展对象的属性和方法。这种动态扩展对象的方式可以让我们更加灵活地处理对象。

实现一些常用的方法和功能:原型对象上已经包含了一些常用的方法和功能,比如 toStringvalueOf 等等。通过在原型对象上定义相应的方法,我们可以为对象实现这些常用方法,以便在开发过程中更加便捷地使用。

举个栗子:

function Person() {}

Person.prototype.sayHello = function() {
  console.log("Hello, I'm a person.");
}

function Student() {}

Student.prototype = Object.create(Person.prototype);

const alice = new Student();

alice.sayHello(); // 输出:Hello, I'm a person.

在这个例子中,我们通过原型链访问了alice对象的原型对象,然后通过它的原型对象调用了sayHello方法。由于Student函数的原型对象继承自Person函数的原型对象,因此alice对象也继承了Person函数的原型对象上的方法和属性。

proto

__proto__是JavaScript中的一个内置属性,它指向对象的原型。在JavaScript中,每个对象都有一个原型对象,这个原型对象包含了对象的所有属性和方法,用来定义对象的共同属性和方法。__proto__属性就是用来表示对象的原型的。

例如,我们可以使用以下代码来创建一个简单的对象,然后查看其__proto__属性:

const person = {
  name: "Alice",
  age: 25
};

console.log(person.__proto__); // 输出:Object {}

上面的代码中,我们定义了一个名为person的对象,它有两个属性:name和age。然后,我们使用console.log()方法输出了person.__proto__属性,这个属性指向的是这个对象的原型对象,也就是Object对象。

需要注意的是,__proto__是一个非标准的属性,在ECMAScript 2015 标准中已经不推荐使用。应该使用Object.getPrototypeOf()方法或Object.setPrototypeOf()方法来操作对象的原型。例如,我们可以使用以下方法来获取一个对象的原型:

const person = {
  name: "Alice",
  age: 25
};

console.log(Object.getPrototypeOf(person)); // 输出:Object {}

上面的代码中,我们使用Object.getPrototypeOf()方法来获取person对象的原型,它返回的是一个Object对象。

__proto__有什么作用

查看对象的原型

我们可以使用__proto__访问一个对象的原型,以便了解它的继承关系。例如:

function Person() {}

const alice = new Person();

console.log(alice.__proto__); // 输出:Person {}

在这个例子中,我们创建了一个Person函数并使用它创建了一个alice对象。然后,通过alice.__proto__访问了alice对象的原型,这个原型就是Person函数的原型对象。

创建对象的原型链

我们可以使用__proto__来创建对象的原型链。例如:

function Person() {}

const alice = {
  name: "Alice"
};

alice.__proto__ = Person.prototype;

console.log(alice instanceof Person); // 输出:true

在这个例子中,我们定义了一个空对象alice,然后将它的原型链指向了Person函数的原型对象。由于alice对象的原型链继承了Person函数的原型,因此它可以被认为是Person类型的实例。

修改对象的原型

我们可以使用__proto__来动态地修改一个对象的原型对象。例如:

function Person() {}

const alice = new Person();

alice.__proto__ = {
  sayHello() {
    console.log("Hello, I'm a new object.");
  }
};

alice.sayHello(); // 输出:Hello, I'm a new object.

在这个例子中,我们创建了一个Person对象alice,然后通过alice.__proto__动态地修改了它的原型对象,将它的原型对象替换成一个新的对象。最后,调用alice.sayHello()方法时输出了Hello, I'm a new object.,说明alice对象的原型已经被成功替换。

原型链

当试图得到一个对象的属性时,如果这个对象本身不存在这个属性,那么就会去它的’_ _ proto_ _'属性(也就是它的构造函数的’prototype’属性)中去寻找。这个寻找的链路就是原型链。

看一个例子:

  // 构造函数
  function Foo(name,age){
    this.name=name;
    this.age=age;
  }
  Object.prototype.toString=function(){
   //this是什么要看执行的时候谁调用了这个函数。
   console.log("I'm "+this.name+" And I'm "+this.age);
  }
  var fn=new Foo('小明',19);
  fn.toString(); //I'm 小明 And I'm 19
  console.log(fn.toString===Foo.prototype.__proto__.toString); //true
  
  console.log(fn.__proto__ ===Foo.prototype)//true
  console.log(Foo.prototype.__proto__===Object.prototype)//true
  console.log(Object.prototype.__proto__===null)//true

来个图帮助理解。

总结

1、所有的引用类型(数组、函数、对象)都可以通过原型可以自由扩展属性(除null以外)。

2、所有的引用类型都有一个’_ _ proto_ _'属性(也叫隐式原型,它是一个普通的对象)。

3、所有的函数都有一个’prototype’属性(这也叫显式原型,它也是一个普通的对象)。

4、所有引用类型,它的’_ _ proto_ _'属性指向它的构造函数的’prototype’属性。(结合2和3)

5、当试图得到一个对象的属性时,如果这个对象本身不存在这个属性,那么就会去它的’_ _ proto_ _'属性(也就是它的构造函数的’prototype’属性)中去寻找。这就是原型链。

 

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

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

相关文章

NumPy 基础知识 :6~10

原文:Numpy Essentials 协议:CC BY-NC-SA 4.0 译者:飞龙 六、NumPy 中的傅立叶分析 除其他事项外,傅立叶分析通常用于数字信号处理。 这要归功于它在将输入信号(时域)分离为以离散频率(频域&am…

Spring Boot集成Druid实现多数据源的两种方式

目录 项目场景: 一、集成com.baomidou的方式 1、maven依赖: 2、 配置文件: 3、 使用注解切换数据源: 二、基于AOP手动实现多数据源原生的方式 1、maven依赖: 2、 配置文件: 3、 多数据源名称类 4…

数字中国理念引领国企人力资源数字化转型与实践

3月初,《数字中国建设整体布局规划》出台,作为中国数字经济发展的重要指导性文件,规划提出了数字中国建设的总体目标和战略方向,文件详细阐述了数字中国内涵,包含数字经济、数字社会、数字政府以及数字生态等内涵。《规…

制造企业该如何选择MES生产管理系统?盘点四大生产管理系统软件

本文将介绍:1、如何选择MES(生产管理系统);2、盘点四款好用的生产管理系统 生产管理系统即MES(Manufacturing Execution System),制造执行系统。是面向车间生产的管理系统。在产品从工单发出到成品完工的过程中,MES系…

1206. 设计跳表

1206. 设计跳表 不使用任何库函数,设计一个 跳表 。 跳表 是在 O(log(n)) 时间内完成增加、删除、搜索操作的数据结构。跳表相比于树堆与红黑树,其功能与性能相当,并且跳表的代码长度相较下更短,其设计思想与链表相似。 例如&a…

如何收集EMC VPLEX 日志和VPLEX日志的简单解读

对于VPLEX遇到的问题,和二线沟通最快最有效的办法就是收集完整的日志,而不是拍一个照片。本文就详细介绍如何收集日志?和那些日志文件对我们分析问题是有价值的。 命令行ssh登录Vplex 管理控制台,然后进入Vplexcli命令行&#xf…

Windows安装Nginx并配置负载均衡

Nginx简介 Nginx是一款自由的、开源的、高性能的HTTP服务器和反向代理服务器;同时也是一个IMAP、POP3、SMTP代理服务器;Nginx可以作为一个HTTP服务器进行网站的发布处理,另外Nginx可以作为反向代理进行负载均衡的实现。 Nginx使用基于事件驱动…

HOJ项目部署(前后端及其判题机)

文章目录HOJ项目部署1 项目准备1.1 拉取HOJ项目到本地1.2 项目包结构解读2 后端部署DataBackup2.1 环境准备1)项目基本数据导入2)Nacos环境配置2.2 修改配置1)修改application-prod.yml2)修改bootstrap.yml3)修改上传文…

【模板特性补充】

目录:前言一、非类型模板参数使用方法使用场景二、模板特化(一)函数模板特化(二)类模板特化1.全特化2.偏特化使用场景三、模板分离编译1. 什么是分离编译2.模板的分离编译3.解决方法四、模板总结前言 打怪升级&#x…

你知道多少接口性能优化的方案?

一、背景 针对老项目,去年做了许多降本增效的事情, 二、接口优化方案总结 1.批处理 批量思想:批量操作数据库,这个很好理解,我们在循环插入场景的接口中,可以在批处理执行完成后一次性插入或更新数据库…

Springboot的自动注入

一、开篇 在平时的开发过程中用的最多的莫属springboot了,都知道springboot中有自动注入的功能,在面试过程中也会问到自动注入,你知道自动注入是怎么回事吗,springboot是如何做到自动注入的,自动注入背后的原理是什么&…

基于 RocketMQ Connect 构建数据流转处理平台

作者:周波,阿里云智能高级开发工程师, Apache RocketMQ Committer 01 从问题中来的 RocketMQ Connect 在电商系统、金融系统及物流系统,我们经常可以看到 RocketMQ 的身影。原因不难理解,随着数字化转型范围的扩大及…

Linux学习笔记——多线程

文章目录补充知识Linux线程概念线程的优点线程的缺点线程异常线程用途多进程的应用场景Linux进程VS线程重新理解进程进程和线程线程共享的进程资源和环境为什么线程切换的成本更低进程和线程的关系Linux线程控制POSIX线程库创建线程线程ID及进程地址空间布局线程终止线程等待线…

pycharm常用的插件

pycharm等IDE 无法编辑bat文件 Chinese Language Pack 汉化插件 vim CodeGlance 右侧地图 将类似于Sublime中的代码小地图嵌入到编辑器窗格中。使用自定义颜色进行语法高亮,同时使用明暗主题。 Rainbow Brackets(必备推荐)收费了 这个插件…

【数据库原理 • 六】数据库备份与恢复

前言 数据库技术是计算机科学技术中发展最快,应用最广的技术之一,它是专门研究如何科学的组织和存储数据,如何高效地获取和处理数据的技术。它已成为各行各业存储数据、管理信息、共享资源和决策支持的最先进,最常用的技术。 当前…

Baumer工业相机堡盟工业相机中预处理相机的特性优势以及行业应用

Baumer工业相机堡盟工业相机如何通过BGAPISDK里显示彩色相机和黑白相机的图像(C#)Baumer工业相机Baumer工业相机的预处理相机的技术背景Baumer工业相机中预处理相机的特性Baumer工业相机中图像压缩相机的特性Baumer工业相机中3D激光相机的特性Baumer工业…

ESP32设备驱动-MAX30102脉搏血氧饱和度和心率监测传感器驱动

MAX30102脉搏血氧饱和度和心率监测传感器驱动 文章目录 MAX30102脉搏血氧饱和度和心率监测传感器驱动1、MAX30102介绍2、硬件准备3、软件准备4、驱动实现1、MAX30102介绍 MAX30102是一款集成脉搏血氧饱和度和心率监测生物传感器模块。 它包括内部 LED、光电探测器、光学元件和…

网页滚动体验,IScroll滚动插件,你安装了类似的滚动页面插件吗

IScroll是一款基于JavaScript的插件,用于在网页中实现平滑滚动效果。 这个插件可以帮助用户创建回到页面顶部和底部的按钮、生成页面导航快照,以及设置滚动时间等功能,从而提升网页的用户体验。 IScroll的特点在于,它能够平滑地…

【15】数据操作reshape、张量的运算

1. N维数组 ① 机器学习用的最多的是N维数组,N维数组是机器学习和神经网络的主要数据结构。 2. 创建数组 ① 创建数组需要:形状、数据类型、元素值。 3. 访问元素 ① 可以根据切片,或者间隔步长访问元素。 ② [::3,::2]是每隔3行、2列访问…

考研数据结构--线性表

线性表 文章目录线性表概述线性表的特点线性表的基本操作线性表的顺序表示概述优缺点操作顺序表的定义顺序表的初始化顺序表的插入顺序表的删除顺序表的查找顺序表的输出顺序表的判空顺序表的销毁main方法测试线性表的链式表示概述优缺点单链表操作单链表的定义单链表的初始化单…