本文将会介绍面向对象,继承,原型等相关知识,涉及的知识点如下:

  • 面向对象与继承
  • CEOC
  • OLOO
  • 臃肿的对象
  • 原型与原型链
  • 修改原型的方式

面向对象与继承

最近学习了下python,还写了篇博文《重拾编程乐趣——我的Python笔记》,加深了我对面向对象的一些理解。

我们会对我们写的程序进行抽象,而不同的语言都提供了不同的抽象工具,比如各种语言里面的数组,集合(键值数组,哈希表,字典等)等提供了对数据的抽象;而VB里面的子程序,类C语言里面的函数,提供了抽象代码段的能力。

有时我们希望将数据和对数据的操作封装到一起,这被称作对象,是一种更高唯独的抽象工具,而这种抽象工具——对象可以对现实世界进行建模。

现实世界中的事物都有一些联系,比如我们可以抽象出来猫,然后又公猫,母猫,显然公猫应该拥有猫的特性,这也就是继承,细分的事物应该有高纬度事物的特点。

想要实现对象和继承这套思维,目前有两种实现方法,分别是CEOC和OLOO。

CEOC

CEOC(class extend other class)是一套基于类和实例的实现方式,这种方式实用的比较广泛,大部分流星的面向对象语言都在使用,比如java,python等。

类作为对象的抽象描述,对象是类的实例,也称作类的泛化,泛化和抽象对应。最恰当的类比就是盖房子了,类就相当于房子的图纸,图纸是对房子属性和功能的描述,根据图纸可以盖很多个类似的房子;另一种类比就是磨具和零件,磨具相当于类,零件相当于对象,通过磨具我们可以造出来很多零件。

其实与其说是面向对象还不如说是面向类编程,在这种机制中解决上面提到的继承逻辑时,是在类上实现的,子类可以继承父类。

在类的机制中更像是对工厂里通过磨具造零件机制的模拟,而非动物世界这种繁衍继承机制的模拟,下面介绍的OLOO则是对世界更好的模拟。

OLOO

OLOO(object link other object)是一套基于对象和原型的实现方式,这种方式唯一实现广泛语言就是js了,熟悉类机制的同学,初次接触这个,可能会觉得不是很好理解,而很多前端同学理解的也不是很明白,之前写过一篇原型的文章,推荐大家阅读《JavaScript原型之路》。

其实面向类的机制有些多此一举了,因为最后使用的是对象,而不是类,那么我们直接让对象可以集成对象不就行了,在这种机制中可以通过某种操作让对象和对象之间可以建立继承的关系,当继承的对象(子对象)中没有某些属性时可以去被继承的对象(父对象)中去查找。

在OLOO中,父对象也可以成为子对象的原型,这有些类似我们的人类的繁衍,每一个人都是一个对象,都是父母所生,而不是用模版建造出来的,每一个人都有一个父亲,孩子和父亲之间有一种特殊的关系,成为父子。

臃肿的对象

来说说JS中的对象机制,JS中的对象显得有些臃肿,JS中的对象承接了两个功能,一是面向对象机制中的对象,另一个是数据抽象中的集合——其他语言中称为键值数组,哈希表或字典。

其实在其它语言中的对象都不耦合集合的功能,比如python中有字典,php中有键值数组,好在es2015中引入新的map类型,来把这个功能解耦出去,但我相信很多人都习惯这么使用了o(╯□╰)o

而本文所说的对象不包括后面的这一部分功能,特指js中面向对象机制中的对象。

原型与原型链

js语言是基于原型的语言,在js中几乎一切都是对象,每个对象都有原型,而原型也是一个对象,也有自己的原型,从而形成原型链。

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

js中提到原型可能有不同的意思,我们得先区分清楚,需要清除到底是哪个原型:

  1. js是基于原型的语言中的prototype
  2. 每个对象都有自己的原型中的prototype
  3. 每个函数都有一个原型属性中的prototype

第一点中的prototype是一个概念,一种机制,而不是具体的什么东西。

第二点中的prototype是说每个对象都有自己的原型对象(父对象),下面我们用[[Prototype]]来指代这个原型对象。

第三点和第二点很容易混淆,每个函数都有一个原型属性,我们用prototype来指代。

es5带来了查看对象原型的方法——Object.getPrototypeOf,该方法返回指定对象的原型(也就是该对象内部属性[[Prototype]]的值)。

console.log(Object.getPrototypeOf({}))

>>> Object.prototype

es6带来了另一种查看对象原型的方法——Object.prototype.__proto__,一个对象的proto 属性和自己的内部属性[[Prototype]]指向一个相同的值 (通常称这个值为原型),原型的值可以是一个对象值也可以是null(比如说Object.prototype.proto的值就是null)。

({}).__proto__

>>> Object.prototype

下面举个例子来说说原型与原型链,以及访问对象属性的时候会发生的行为:

// a ---> b 代表b是a的原型

修改原型的方式

在js中创建和修改原型的方法有很多,下面一一列举出来。

在下面的例子中我们将对象a的[[Prototype]]指向b。

// a ---> b

使用普通语法创建对象

这是最容易被大家忽略的方法,在js中你是绕不过原型的,不经意间就创建了原型

var o = {a: 1};

// o ---> Object.prototype ---> null

var a = [];

// a ---> Array.prototype ---> Object.prototype ---> null

function f(){}

// f ---> Function.prototype ---> Object.prototype ---> null

这种方法无法让a的[[Prototype]]指向b。

使用构造器创建对象

构造函数就是一个普通的函数,只不过这次不是直接调用函数,而是在函数前加上new关键字。

每个函数都有一个prototype属性,通过new关键字新建的对象的原型会指向构造函数的prototype属性,所以我们可以修改构造函数的prototype属性从而达到操作对象原型的目的。

为了让b继承a,需要有一个构造函数A

var b = {};

function A() {};

A.prototype = b;

var a = new A();

Object.getPrototypeOf(a) === b;

// true

// a ---> A.prototype === b

使用 Object.create 创建对象

ES5带来了Object.create接口,可以让我们直接设置一个对象原型

var b = {};

var a = Object.create(b);

Object.getPrototypeOf(a) === b;

// true

// a ---> b

Object.setPrototypeOf

ES6带来了另一个接口,可以绕过创建对象的过程,直接操作原型

var a = {};

var b = {};

Object.setPrototypeOf(a, b);

Object.getPrototypeOf(a) === b;

// true

// a ---> b

proto

ES6还带来了一个属性,通过这个属性也可以直接操作原型

var a = {};

var b = {};

a.__proto__ = b;

Object.getPrototypeOf(a) === b;

// true

// a ---> b

注意这个属性在ES6规范的附录中,也就意味着不是所有的环境都会有这个属性。

使用 class 关键字

ES6引入了以class语法糖,通过extends关键字我们也可以实现继承,但是无法直接操作对象的原型,而是要借助“类”,其实就是构造函数和函数的prototype属性。

class B {}

class A extends B {}

var a = new A();

Object.getPrototypeOf(a) === A.prototype;

// true

// a ---> A.prototype === B的实例

总结

详解JavaScript中的原型和继承-转自颜海镜大大的更多相关文章

  1. 详解JavaScript中的原型

    前言 原型.原型链应该是被大多数前端er说烂的词,但是应该还有很多人不能完整的解释这两个内容,当然也包括我自己. 最早一篇原型链文章写于2019年07月,那个时候也是费了老大劲才理解到了七八成,到现在 ...

  2. 详解Javascript中的原型与原型链

    目录 知识点 参考资料 结束语 知识点 面向对象编程 我们熟悉的Java和C#里,面向对象的两个基本概念是类class和实例instance,而ES6以前的Javascript并没有设计class. ...

  3. (转载)详解Javascript中prototype属性(推荐)

    在典型的面向对象的语言中,如java,都存在类(class)的概念,类就是对象的模板,对象就是类的实例.但是在Javascript语言体系中,是不存在类(Class)的概念的,javascript中不 ...

  4. 【转】详解JavaScript中的this

    ref:http://blog.jobbole.com/39305/ 来源:foocoder 详解JavaScript中的this JavaScript中的this总是让人迷惑,应该是js众所周知的坑 ...

  5. 详解javascript中的this对象

    详解javascript中的this对象 前言 Javascript是一门基于对象的动态语言,也就是说,所有东西都是对象,一个很典型的例子就是函数也被视为普通的对象.Javascript可以通过一定的 ...

  6. 【转】JavaScript中的原型和继承

    请在此暂时忘记之前学到的面向对象的一切知识.这里只需要考虑赛车的情况.是的,就是赛车. 最近我正在观看 24 Hours of Le Mans ,这是法国流行的一项赛事.最快的车被称为 Le Mans ...

  7. 详解 javascript中offsetleft属性的用法(转)

    详解 javascript中offsetleft属性的用法 转载  2015-11-11   投稿:mrr    我要评论 本章节通过代码实例介绍一下offsetleft属性的用法,需要的朋友可以做一 ...

  8. this详解:JAVASCRIPT中的this到底是谁?

    语法 this 全局对象 在全局执行上下文(函数之外),this引用的是全局对象. console.log(this.document === document); // true // In web ...

  9. javascript中的原型和继承

    javascript一直是初学者口中的难点,甚至一些有些许工作经验的人也不太明白其中的原理,而我就是那个初学者,前段时间在阮一峰老师的博客上看了一篇文章<javascript继承机制的设计思想& ...

随机推荐

  1. vue-cli搭建项目结构及引用bootstrap

    vue-cli脚手架工具快速构建项目架构: 1.首先默认了有已经安装了node,然后依次执行以下命令: npm install -g vue-cli                   全局安装vue ...

  2. IIS的安装与配置详细图解教程

    IIS是Internet Information Services(互联网信息服务)的简称,是有微软公司提供的基于在windows操作系统环境下运行的互联网服务.此处将介绍如何安装配置IIS来构架自己 ...

  3. WebApp开发技巧大全

    1.开发成本较低使用web开发技术就可以轻松的完成web app的开发 2.升级较简单升级不需要通知用户,在服务端更新文件即可,用户完全没有感觉 3.维护比较轻松和一般的web一样,维护比较简单,它其 ...

  4. Unity脚本中可以引用的类型

    Hierarchy(层级视图)面板里的对象,或者 Project(工程视图)里的Prefab.

  5. ZBrush 4R7中自定义笔刷

    为了便于雕刻,ZBrush®很人性化地设计了自定义笔刷.随着ZBrush软件版本不断更新,功能也在不断完善.只是在笔刷面板ZBrush软件就为用户提供了上百种之多,如果我们想要用某种笔刷,一个个找起来 ...

  6. ZBrush软件特性之Stencil模板调控板

    在ZBrush中使用Stencil模板我们了解的所有绘图工具,通过它确定模板周围与涂画或模型的位置.本文将详解ZBrush®中如何使用“曲线板”自定义形状. 使用模版 ZBrush模版的作用象我们了解 ...

  7. ZBrush为电影制作设计独特的生物概念

    任何一个从事3D行业的艺术家,在雕刻和画画方面,都要有牢固的基本技能,还要会使用一些软件.比如今天我们提到的这位概念设计师.插画师和艺术导演Ian Joyner,他在创作新角色之前,都会思考如何以及为 ...

  8. luoguP1390 公约数的和 数学推导_双倍经验

    Code: #include <bits/stdc++.h> #include <tr1/unordered_map> #define setIO(s) freopen(s&q ...

  9. 路飞学城Python-Day22

  10. JAVA 重载方法,参数为NULL时,调用的处理 (精确性原则)

    引子:大家可以思考一下下面程序的输出结果 public class TestNull { public void show(String a){ System.out.println("St ...