(JavaScript)原型与原型对象

news/2024/6/18 20:54:07

第一次记录自己学习的脚步,我选择了JavaScript中自认为比较熟悉的一小部分来说,诚挚的希望能够得到各位前辈的批评与指正。而对于看到我这篇笔记希望从这篇笔记中收获知识的读者,我希望你们可以参考权威,拥有自己的真知灼见而不听我一家之言,以免有不正确的地方误导了读者。

1.原型,原型对象是什么?

**1.原型(prototype)是函数的一个属性,这个属性是个指针指向原型对象。
2.原型对象(prototype object)是一个属于其所在函数的空对象,可以通过它给函数添加属性和方法。**
值得注意的是原型对象也拥有一个属性——constructor指向其函数。

通过一张图我们可以更好的理解这几者的关系:

原型对象

上图给我们传达了几个信息:
**1.实例拥有一个属性[[prototype]],这个属性指向其构造函数的原型对象。
2.原型对象也是构造函数的实例**

2.那么,这个东西有什么用?

我们知道,JavaScript是一个基于对象的语言,而与Java等语言不同的是JavaScript没有类的概念。而要实现类的功能我们则需要模拟类。在模拟类的实现中使用原型和原型对象我们就可以更好的创建具有封装性,共享性的类(对象),而这种创建类(对象)的模式就叫原型模式。

这也解释了为什么在《JavaScript高级程序设计》中描述原型以及原型对象用于创建对象,而在《JavaScript权威指南》中描述原型以及原型对象用于创建类。(因为在JavaScript中没有类,有类也只是对象模拟出来的,包括ES6中的class关键字)

3.该如何使用它?

原型模式模拟类十分简单:

var Foo = function(){}
Foo.prototype.username = 'ec'
console.log(Foo.prototype)  // --> a{username = 'ec'}
var f = new Foo()
console.log(f.username)     //--> 'ec'
console.log(Foo.username)   //--> underfined

我们可以发现两个信息:
**1.原型对象与它所在函数同名
2.属性已经被添加进了原型对象中
3.使用时必须实例化构造器函数。**

需要注意的是原型模式模拟类是有缺点的,例如以下代码:

function Person(){}
Person.prototype = {
  constructor: Person,
  name: "李小山",
  age: 20,
  family: [
    "李大山",
    "张晓梅",
  ],
}
var person1 = new Person()
var person2 = new Person()
person1.family.push("李巨山")
console.log(person1.family)  //--> ["李大山", "张晓梅", "李巨山"]
console.log(person2.family)  //--> ["李大山", "张晓梅", "李巨山"]

从上面这个例子我们可以得到几个信息:
**1.因为原型模式规定我们在原型对象上添加属性与方法,所以无法传递初始化参数
2.因为过度的“共享”以至于当一个实例改变了引用类型的值,所有实例的该值都会被改变。**

以上的原因就造成了很少有使用纯的原型模式创建对象,而其他混合使用原型模式的创建对象模式就不在这里展开说了。

4.还是不太明白原型对象、对象、函数

终于讲到了这部分,这个部分我们可以提一个更加具体的问题:
原型对象与对象、函数、构造函数、实例的关系是什么?
首先是函数与构造函数的区别:

  • 构造函数需要new操作符实例化才能使用
  • 构造函数没有return语句
  • 构造函数this指向调用者往往是调用构造函数的实例本身,而函数使用this则会指向window全局对象
  • 构造函数名首字母大写(非强制性的)

实例就是构造函数创建出来的对象,拥有构造函数的属性与方法

知道了这些后我们就可以通过这张图来明确它们之间的关系了:

图片描述

这个图看似唬人,其实只需要知道三点就可以秒懂了:
1.JavaScript中一切皆是对象
2.所有对象有[[prototype]]属性,指向其构造函数的原型对象
3.所有函数都有prototype属性,指向其原型对象
4.所有实例都有constructor属性,指向其构造函数

图中有两个地方可能比较难以理解:

  • 为什么内置对象Function()的原型对象function()是个函数对象?

因为内置对象Function()也是函数,而函数就是function,这就造成了一种鸡生蛋、蛋生鸡的问题,而让Function()的原型对象为函数对象就可以添加函数方法给Function(),这也解释了为什么Function()的[[prototype]]属性也指向其原型对象。

  • 内置对象的原型对象的[[prototype]]属性指向谁?

这也是一个鸡生蛋、蛋生鸡的问题,是对象创建了对象,那么追根溯源谁真正创建了对象呢?答案就是Null空。(图中这个地方箭头指向错误,望见谅)

至此,我们算是大致了解了JavaScript中有关于原型的基本知识了,其实还有很多问题我们没有解决,比如比原型模式更好的创建对象模式,还有关系图中有关于继承的部分都还没用详细说明。篇幅有限,下次再聊。


http://www.niftyadmin.cn/n/4636574.html

相关文章

挖出最大财宝

Description 给你一个大小为m*n的矩阵Mine表示矿场,里面有丰富的宝石。Mine(i,j)若大于0,表示该点存在宝石,其值为宝石价值;若等于0,表示的是不可进入的区域;若小于-1表示危险区域。当你选择一个点挖宝石的…

【Linux操作系统】多线程抢票逻辑——学习互斥量(锁)函数接口

文章目录 1.进程线程间的互斥相关背景概念2.联系代码学习同步互斥问题3.互斥量(锁)的函数接口3.1初始化互斥量3.2销毁互斥量3.3互斥量加锁和解锁3.4改进多线程抢票代码 1.进程线程间的互斥相关背景概念 临界资源:多线程执行流共享的资源就叫…

1067 Sort with Swap(0, i)

Given any permutation of the numbers {0, 1, 2,…, N−1}, it is easy to sort them in increasing order. But what if Swap(0, *) is the ONLY operation that is allowed to use? For example, to sort {4, 0, 2, 1, 3} we may apply the swap operations in the followi…

1090 Highest Price in Supply Chain

A supply chain is a network of retailers(零售商), distributors(经销商), and suppliers(供应商)-- everyone involved in moving a product from supplier to customer. Starting from one root suppl…

linux 设备文件和设备之间联系的建立

<设备驱动模型> 注&#xff1a;几乎所有的设备结构体都包含"strcut kobject kobj"和"srtuct list_head list"该结构体。struct kobject kobj: 该结构体用于构建Linux设备驱动模型的模型建立 struct list_head { struct list_head *prev,*next; }; 该…

mysql-存储过程-触发器-事务---4

本节所讲内容&#xff1a; 存储过程 触发器事务一、存储过程 什么是存储过程 大多数SQL语句都是针对一个或多个表的单条语句。并非所有的操作都怎么简单。经常会有一个完整的操作需要多条才能完成。存储过程&#xff08;Stored Procedure&#xff09;是在大型数据库系统中&…

Linux系统安装与初用 实验报告

南京信息工程大学实验报告 一、实验目的 1.掌握 linux 系统的安装方法 2.理解 linux 系统安装过程中涉及的基础知识 3.熟悉 linux 系统的操作环境 4.尝试简单的 linux shell 命令 二、实验准备 1. 围绕下述问题结合教材、课件、互联网学习指定内容。 问题&#xff1a; &#xf…

Maven学习笔记三(Eclipse创建Maven项目)

配置 Eclipse Maven 环境1.配置 Manen 地址将下载的Maven导入进来&#xff0c;然后勾选使用2.设置 setting.xml 地址选中Maven下conf目录下的settings.xml&#xff0c;然后local Repository会自动识别出设置的local Repository创建 Maven 项目选中模板 &#xff08;如果是创建w…