资讯专栏INFORMATION COLUMN

(JavaScript)原型与原型对象

Muninn / 892人阅读

摘要:值得注意的是原型对象也拥有一个属性指向其函数。以上的原因就造成了很少有使用纯的原型模式创建对象,而其他混合使用原型模式的创建对象模式就不在这里展开说了。

第一次记录自己学习的脚步,我选择了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中有关于原型的基本知识了,其实还有很多问题我们没有解决,比如比原型模式更好的创建对象模式,还有关系图中有关于继承的部分都还没用详细说明。篇幅有限,下次再聊。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/107626.html

相关文章

  • 理解JavaScript的核心知识点:原型

    摘要:首先,需要来理清一些基础的计算机编程概念编程哲学与设计模式计算机编程理念源自于对现实抽象的哲学思考,面向对象编程是其一种思维方式,与它并驾齐驱的是另外两种思路过程式和函数式编程。 JavaScript 中的原型机制一直以来都被众多开发者(包括本人)低估甚至忽视了,这是因为绝大多数人没有想要深刻理解这个机制的内涵,以及越来越多的开发者缺乏计算机编程相关的基础知识。对于这样的开发者来说 J...

    iKcamp 评论0 收藏0
  • 进击JavaScript之(四)原型原型

    摘要:每一个由构造函数创建的对象都会默认的连接到该神秘对象上。在构造方法中也具有类似的功能,因此也称其为类实例与对象实例一般是指某一个构造函数创建出来的对象,我们称为构造函数的实例实例就是对象。表示该原型是与什么构造函数联系起来的。 本文您将看到以下内容: 传统构造函数的问题 一些相关概念 认识原型 构造、原型、实例三角结构图 对象的原型链 函数的构造函数Function 一句话说明什么...

    XBaron 评论0 收藏0
  • JavaScript中的原型原型

    摘要:前言作为前端高频面试题之一,相信很多小伙伴都有遇到过这个问题。 前言 作为前端高频面试题之一,相信很多小伙伴都有遇到过这个问题。那么你是否清楚完整的了解它呢? 国际惯例,让我们先抛出问题: 什么是原型、原型链 它们有什么特点 它们能做什么 怎么确定它们的关系 或许你已经有答案,或许你开始有点疑惑,无论是 get 新技能或是简单的温习一次,让我们一起去探究一番吧 如果文章中有出现纰...

    laoLiueizo 评论0 收藏0
  • JavaScript深入之从原型原型

    摘要:深入系列的第一篇,从原型与原型链开始讲起,如果你想知道构造函数的实例的原型,原型的原型,原型的原型的原型是什么,就来看看这篇文章吧。让我们用一张图表示构造函数和实例原型之间的关系在这张图中我们用表示实例原型。 JavaScript深入系列的第一篇,从原型与原型链开始讲起,如果你想知道构造函数的实例的原型,原型的原型,原型的原型的原型是什么,就来看看这篇文章吧。 构造函数创建对象 我们先...

    Songlcy 评论0 收藏0
  • 深入理解:JavaScript原型继承

    摘要:深入理解原型与继承看过不少书籍,不少文章,对于原型与继承的说明基本上让人不明觉厉,特别是对于习惯了面向对象编程的人来说更难理解,这里我就给大家说说我的理解。 深入理解:JavaScript原型与继承 看过不少书籍,不少文章,对于原型与继承的说明基本上让人不明觉厉,特别是对于习惯了面向对象编程的人来说更难理解,这里我就给大家说说我的理解。 首先JavaScript是一门基于原型编程的语言...

    mengbo 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<