资讯专栏INFORMATION COLUMN

JS对象(1)重新认识面向对象

superw / 3491人阅读

摘要:对象重新认识面向对象面向对象从设计模式上看,对象是计算机抽象现实世界的一种方式。除了字面式声明方式之外,允许通过构造器创建对象。每个构造器实际上是一个函数对象该函数对象含有一个属性用于实现基于原型的继承和共享属性。

title: JS对象(1)重新认识面向对象
date: 2016-10-05
tags: JavaScript

0x00 面向对象

从设计模式上看,对象是计算机抽象现实世界的一种方式。

面向对象编程(object-oriented programming)的最主要目的是提高程序的重复使用性。

我们说,对象具有属性(property)和方法(function),(其实本质上方法也是一种属性)在面向对象的设计模式中,属性是一种描述,描述对象的状态,比如一个人一天 24 小时的情绪,每个时刻他的情绪都具有不同的状态,喜怒哀乐,抑郁癫狂,贪嗔痴念,当然情绪只是生而为人的众多状态中的一种而已。而对象中的方法是一种功能,它的功能就是操作对象的属性。比如,吃饭可以改变一个人的状态,对吃货而已,吃饱以后会觉得特别幸福,吃饭是一种功能,它改变了一个人的情绪,让人觉得幸福。

那么,反过来细想,人是一个对象,它具有情绪,他还要吃饭。所以可以说,对象是对属性和方法的一种封装。

0x01 南拳北腿

对象中的几个概念:

一切事物皆对象

对象具有封装和继承特性

对象与对象之间使用消息通信,各自存在消息隐藏

然而,面向对象仅仅是一个概念或者编程思想而已,它不应该依赖于某个语言存在。比如 Java 采用面向对象思想构造其语言,它实现了类、继承、派生、多态、接口等机制。但是这些机制,只是实现面向对象编程的一种手段,而非必须。换言之,一门语言可以根据其自身特性选择合适的方式来实现面向对象。

JavaScript 语言是通过一种叫做原型(prototype) 的方式来实现面向对象编程的。

所以无论是基于类的(class-based)面向对象,还是 基于原型的 (prototype-based) 面向对象 也都只是为实现面向对象这一理念在构造客观世界的两种不同方式而已。

0x02 类 or 原型

在基于类的面向对象方式中,对象(object) 依靠 类(class) 来产生。而在基于原型的面向对象方式中,对象(object) 则是依靠 构造器(constructor) 利用 原型(prototype) 构造出来的。

而关于这两种方式谁更为彻底地表达了面向对象的思想,目前尚有争论。

类是一个抽象概念而并非实体,而对象的产生是一个实体的产生;
原型方式中的构造器 (constructor) 和原型 (prototype) 本身是其他对象通过原型方式构造出来的对象。

在类式面向对象语言中,对象的状态 (state) 由对象实例 (instance) 所持有,对象的行为方法 (method) 则由声明该对象的类所持有,并且只有对象的结构和方法能够被继承;而在原型式面向对象语言中,对象的行为、状态都属于对象本身,并且能够一起被继承。

JavaScript 是一种基于原型的编程语言,并没有 class 语句,而是把函数用作类。当然,ES6 提供了 class 的语法糖

0x03 JavaScript 中的面向对象

ECMAScript 是一门彻底的面向对象的编程语言,JavaScript 是其中的一个变种 (variant)。它提供了 6 种基本数据类型,即 Boolean、Number、String、Null、Undefined、Object。为了实现面向对象,ECMAScript设计出了一种非常成功的数据结构 - JSON(JavaScript Object Notation), 这一经典结构已经可以脱离语言而成为一种广泛应用的数据交互格式。

ECMAScript除了字面式声明(literal notation) 方式之外, 允许通过构造器(constructor) 创建对象。每个构造器实际上是一个函数(function) 对象, 该函数对象含有一个prototype属性用于实现基于原型的继承(prototype-based inheritance)共享属性(shared properties)。对象可以由 “new 关键字 + 构造器调用” 方式来创建。

但需要指出的是,这与java语言的new含义毫无关系,因为其对象构造的机理完全不同。ECMAScript 完全可以用其它非new表达式来用调用构造器创建对象。

0x04 原型链

涉及到继承这一块,Javascript 只有一种结构,那就是:对象。在 javaScript 中,每个对象都有一个指向它的原型对象(prototype)的内部属性_proto_属性。而这个原型对象又有自己的原型,直到某个对象的原型为 null 为止(也就是不再有原型指向),组成这条链的最后一环。这种一级一级的链结构就称为原型链(prototype chain)

一张经典的 JavaScript 原型链图可以揭示一切:

要理解上图,只需要搞明白两个属性(指针)的区别,即是_proto_ 属性和 prototype 属性。

每个构造函数都有一个 prototype 属性,该属性是一个指针,指向该构造函数的原型

而实例中包含一个属性 _proto_ 属性,该属性是一个指针,指向该实例所属的构造函数创建的原型

不同的浏览器对实例中的 _proto_ 属性表示不同。

每创建一个构造函数便会相应的创建一个与其相对应的原型对象(由构造函数创建出来的原型对象,JS 引擎自动创建)。

在默认情况下,构造函数创建的原型对象都会有一个 constructor 属性,而这个属性指向 prototype 属性所在的那个函数。

所以,我们可以得出一个结论,构造函数的 prototype 和由该构造函数创建的实例的 _proto_ 指向的是内存中的的同一块地址,也正是如此,才使得在原型中定义的方法和属性具有共享的基础。

有了 原型链,便可以定义一种所谓的 属性隐藏机制,并通过这种机制实现继承。ECMAScript 规定,当要给某个对象的属性赋值时,解释器会查找该对象原型链中第一个含有该属性的对象(注:原型本身就是一个对象,那么原型链即为一组对象的链。对象的原型链中的第一个对象是该对象本身)进行赋值。

所以,当试图访问一个对象的属性时,它不仅仅在该对象上搜寻,还会搜寻该对象的原型,以及该对象的原型的原型,依此层层向上搜索,直到找到一个名字匹配的属性或到达原型链的末尾。

0x05 JavaScript 的类式继承实现

基于原型的继承方式,虽然实现了代码复用,但其行文松散且不够流畅,可阅读性差,不利于实现扩展和对源代码进行有效地组织管理。不得不承认,类式继承方式在语言实现上更具健壮性,且在构建可复用代码和组织架构程序方面具有明显的优势。

0x06 JavaScript 私有成员实现

JavaScript 没有实现面向对象中的信息隐藏,即私有和公有。与其他类式面向对象那样显式地声明私有公有成员的方式不同,JavaScript 的信息隐藏就是靠闭包实现的。

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

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

相关文章

  • 深入浅出面向对象和原型【番外篇——重新认识new】

    摘要:前言我们在深入浅出面向对象和原型概念篇在这篇文章中了解到了如何使用解决重复创建浪费内存的问题,其中的关键就是,那么这篇文章让我们来重新了解的前世今生一个苦逼年级主任的故事开学啦高一年级主任龚主任需要为全年级每一位理科班新生录入学号并为每一位 前言 我们在深入浅出面向对象和原型【概念篇2】在这篇文章中了解到了如何使用new Function解决重复创建浪费内存的问题,其中的关键就是new...

    Apollo 评论0 收藏0
  • 好文章必读 - 收藏集 - 掘金

    摘要:方法即为收集器,它接收高阶函数和的后端掘金年的第一天,我坐在独墅湖边,写下这篇文章。正因如此,所以最全系列教程后端掘金是从版本开始引入的一个新的,可以替代标准的。 设计模式之单例模式 - 掘金前言 作为一个好学习的程序开发者,应该会去学习优秀的开源框架,当然学习的过程中不免会去阅读源码,这也是一个优秀程序员的必备素养,在学习的过程中很多人会遇到的障碍,那就是设计模式。很多优秀的框架会运...

    FrozenMap 评论0 收藏0
  • 设计模式(通往高手之路的必备技能)

    摘要:设计模式的定义在面向对象软件设计过程中针对特定问题的简洁而优雅的解决方案。从前由于使用的局限性,和做的应用相对简单,不被重视,就更谈不上设计模式的问题。 ‘从大处着眼,从小处着手’,以前对这句话一知半解,自从踏出校门走入社会,开始工作以来,有了越来越深的理解,偶有发现这句话用在程序开发中也有用,所以,近段时间开始尝试着分析jQuery源码,分析angularjs源码,学习设计模式。 设...

    paraller 评论0 收藏0
  • 从ES6重新认识JavaScript设计模式(五): 代理模式和Proxy

    摘要:此时,链家起到的作用就是代理的作用。验证代理构造函数第二个参数中的方法,可以很方便的验证向一个对象的传值。 1 什么是代理模式 showImg(https://segmentfault.com/img/remote/1460000015800706?w=1262&h=464); 为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理...

    verano 评论0 收藏0

发表评论

0条评论

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