1. 前言

作为Java 帝国的未来继承人,Java小王子受到了严格的教育, 不但精通Java语言、Java虚拟机、java类库和框架,还对各种官方的Java规范了如指掌。

近日他听说一个叫做Javascript的屌丝逆袭了, 成功地建立了一个独立的王国, 不但成了前端编程之王, 还不断地蚕食Java帝国的领地 !

按照小王子宫廷老师的说法: 想当年, 这家伙只是运行在浏览器中,完完全全是蹭了Java的热度这才发展起来, 现在竟然回过头来要欺负我们, 还有没有天理了? 是可忍孰不可忍? !

小王子可不这么认为, 存在必然是合理的,javascrip必有独特之处, 俗话说知己知彼,百战不殆,他觉得有必要去Javascript王国刺探一下,搜集一下情报, 看看这个曾经的浏览器中的面向对象语言是怎么回事, 为什么那么多码农趋之若鹜。

2. 初步印象

乔装打扮以后,小王子来到Javascript 王国,这里看起来一派生气勃勃的景象,人们随性而奔放, 不像Java帝国那么严肃而呆板, 让人感觉心情愉悦。

不过令小王子感到不可思议的是, 这里竟然没有官方提供的类库!   人们干活用的工具五花八门,让人眼花缭乱, 什么AngularJS, React , Backbone,Vue, Ember,JQuery, ......   互相之间还吵来吵去,争来争去,煞是热闹。

对比这下,Java帝国有着严密的统治,有着官方提供的庞大类库, 还有一统天下的Web框架 SSH/SSM ,再加上各种各样的Java规范, 码农们只需要拿来学习,干活就行。

没有了选择的烦恼, 但同时也减少了选择的权利, 是好还是坏?  小王子自己也不知道。

小王子还注意到Javascript王国的人写程序几乎没人使用IDE, 找个趁手的文本编辑器就可以开工, 然后扔到浏览器中去运行测试,真是轻量级啊!  唉, 我们Java帝国还在争论IntelliJ IDEA和Eclipse孰优孰劣,   实在是没有必要啊。

3. 没有类怎么创建对象?

随着调查的深入,小王子愈发觉得吃惊, 这里竟然没有类的概念!  一个面向对象的语言竟然没有类! 这和小王子从出生就被灌输的概念可是背道而驰!

没有类怎么创建对象 ? 小时候宫廷老师经常说: 先写一个类, 然后才能从这个类new出一个对象出来 。

可是眼前却有着无数的javascript对象, 他们在不断地产生、消亡,一起辛苦地工作,支撑起庞大的、生机勃勃的帝国。

这些对象是从哪里来的?  小王子百思不得其解, 正值正午时分, 小王子看到前面有一家JSON酒馆,决定先歇歇脚,美美地吃一顿再说。

小王子要了二斤熟牛肉,三碗酒,正要开始享用, 只听到旁边桌子的一个穿着长袍的人问道:哎,你说的那个对象的原型是什么? 

另一位戴眼镜的则低声说:嘘,噤声,国王刚颁布命令,原型法是我们帝国的秘密,禁止公开讨论,以防被Java帝国给学了去。

小王子心中一动, 马上把小二叫来,要来上等酒菜, 送到邻桌,请两位吃酒。 一番酒喝下来, 小王子终于获得了两人的初步信任, 原来他们还是负责审查javscript语言规范的官员。

小王子问道: “我家世代经商, 走南闯北,去过C++王国,Java帝国, C#帝国, 他们都是号称面向对象的语言, 都有class 和 object的区分, 可是到了咱们javascript王国, 我怎么连一个class 都没有看到啊? ”

戴眼镜的官员说: “我们不用class, 那玩意儿太不直观了 !”

小王子暗暗称奇, 可是仔细一想, 好像就是这样啊, 想当初我学习Java的时候, 费了好大的劲才接受了class这个概念,实际上面向对象的系统,不就是对象之间的交互吗? 要类干什么?

然后小王子问了一个关键问题: “没有class, 怎么创建对象啊”

“外乡人, 没那么复杂,你想想什么是对象啊,不就是属性加上方法吗? 你看看我们这就创建一个对象出来 ”  这位官员说着,手指头沾着酒水在桌子上写了起来:

看到没有,这个animal对象定义了一个属性name, 和一个方法 eat , 简单吧?”

的确是简单又明了,完全不需要class, 一个对象就创建了,小王子面前似乎打开了一扇新的大门。

“由于对象并不和类关联, 我们可以随意地给这个对象增加属性:” 眼镜官员补充到。

“还能这么玩?!” 小王子被惊到了,没有类的约束,这些对象也太自由了吧。

4. 没有类怎么继承?

“那继承怎么实现, 继承可是面向对象的重要概念啊”

眼镜官员说: “简单啊,继承不就是让两个对象建立关联嘛!  在我们javascript王国,每个对象都有一个特殊的属性叫做__proto__, 你可以用这个属性去关联另外一个对象(这个对象就是所谓的原型了) , 来我给你画一下”

这段酒水写成的代码不长,但是却深深地震撼了小王子, 因为其中信息量非常巨大,隐藏了“原型”的秘密, 小王子不由得陷入了深思:

对象dog 的原型是animal (注意:也是一个对象),  对象cat的原型也是animal 。

无论是dog还是cat ,都没有定义eat()方法, 那怎么可以调用呢?

当eat方法被调用的时候,先在自己的方法列表中寻找, 如果找不到,就去找原型中的方法, 如果原型中找不到, 就去原型的原型中去寻找......   最后找到Object那里, 如果还找不到, 那就是未定义了。

这里的这几个对象肯定是通过__proto__建立了一个原型链!

嗯, 我师父给我讲JVM虚拟机的时候, 也提到了一个对象在执行方法的时候,需要查找方法的定义,这个查找的次序也是先从本对象所属的类开始, 然后父类, 然后父类的父类...... 直到Object,  思路是一模一样的!

只不过Java 的方法定义是在class中, 而这个javascript 的方法就在对象里边, 现在我觉得似乎在对象里更加直观一点啊。

属性和方法应该类似,也是沿着原型链向上查找, 不过这里dog的name属性似乎覆盖了animal的name属性, 还有那个this, 在调用dog.eat()的时候,应该是指向dog这个对象的。

看来面向对象的理念都是想通的啊。 想着想着,小王子脸上竟然露出了笑容。

看到小王子像程序卡住一样,不动了,  穿长袍的官员推了小王子一把: 外乡人, 你怎么了?

小王子意识到自己的失态, 赶紧说: “哦,没啥, 我觉得你们使用的这个’原型‘的办法很精妙啊, 完全不用类就实现了继承。”

眼镜官员一愣: “外乡人, 看来你悟性不错, 帝国的秘密已经被你给洞察了, 不过很多新来的程序员就不容易体会到这一点, 于是我们就做了一个变通, 让javascript可以像Java那样new 出对象出来。说来惭愧, 这完全是为了迁就那些C++,Java, C#程序员啊 ”

5. 向Java靠拢

小王子说:”什么变通办法? 难道你们也开始使用类了吗?“

“不不, 我们提供了一个叫做构造函数的东西。还是给你写点儿代码吧 ”  官员说着,又蘸着酒水写了起来:

小王子说道: “那个function 已经有点 class的感觉了啊,  天呐我竟然看到了this这个关键字, 对了那个Student是你故意写的大写吗? ”

“是啊 , 这样以来看起来就像Java的类了。但是,中间有个问题,你看出来了吗? ”

小王子想了一阵:“ 是不是说每个新创建对象都有一个sayHello函数? 在Java中函数都是定义在class 上的。 如果定义对象上, 那就意味着每个对象都有一份, 太浪费了。”

“是的,所以我们得提供一种更加高效的办法, 把这个sayHello函数放到另外一个地方去! ”

“放到哪里? ”

“记得我们刚才说的原型链吗?  当一个对象调用方法的时候,会顺着链向上找,所以我们可以创建一个原型对象,其中包含sayHello函数,  让andy, lisa这些从Student创建起来的对象指向这个原型就ok了。”

“可是你这里只有构造函数Student,  在哪里创建原型对象呢?  怎么把andy,lisa 这些对象的__proto__指向原型对象呢? 不会让我手工来指定吧。”

眼镜官员瞪了一眼小王子说: “我们javascript帝国肯定不会这么麻烦程序员的, 我们可以把这个原型对象放到Student.prototype这个属性中(注意,不是__proto__), 这样一来,每次当你创建andy,lisa这样的对象时, javascript 就会自动的把原型链给建立起来!”

小王子面露难色:“唉,这理解起来有点难啊。”

"还是画个图吧, 当你去new Student的时候,javascript会建立这样的关系链:"

小王子说: “明白了,这个所谓的构造函数Student 其实就是一个幌子啊, 每次去new Student的时候,确实会创建一个对象出来(andy或者lisa) , 并且把这个对象的原型(__proto__)指向 Student.prototype这个对象,这样一来就能找到sayHello()方法了。”

眼镜官员回答:“没错,这个地方容易让人混淆的就是__proto__和prototype这两个属性, 唉,我也不知道最早为什么这么干, 实在是不优雅。”

“是啊,这个构造函数再加上prototype的概念,实在是让人费解, 所以我们商量着提供一点语法糖降低程序员的负担。”   长袍官员附和到。

6. 语法糖

听到语法糖,小王子觉的很亲切, 因为Java 中也提供了很多方便程序员的语法糖。

当长袍官员写出javascript的语法糖的时候, 小王子不由得大吃一惊:

这语法糖已经把javascript变得非常像Java, C#,C++的类了, 看来javascript帝国为了“讨好”程序员, 已经努力的在改变了, 我们java帝国看来得加油啊。

小王子现在明白了Javascript是一个基于原型实现的面向对象的语言, 根本没有类的概念, 新的方式给小王子的思维观念带来了重大的冲击。

在这里待久了,他又了解到javascript强大的函数式编程,越来越喜欢javascript, 都有点乐不思蜀了。

小王子还会回到Java帝国吗?

Java学习交流QQ群:523047986  禁止闲聊,非喜勿进!

javascript王国的一次旅行,一个没有类的世界怎么玩转面向对象?的更多相关文章

  1. 请写出一段JavaScript代码,要求页面有一个按钮,点击按钮弹出确认框。程序可以判断出用

    请写出一段JavaScript代码,要求页面有一个按钮,点击按钮弹出确认框.程序可以判断出用 户点击的是“确认”还是“取消”. 解答: <HTML> <HEAD> <TI ...

  2. JavaScript中一个对象数组按照另一个数组排序

    JavaScript中一个对象数组按照另一个数组排序 需求:排序 const arr1 = [33, 11, 55, 22, 66]; const arr2 = [{age: 55}, {age: 2 ...

  3. 2015年3月26日 - Javascript MVC 框架DerbyJS DerbyJS 是一个 MVC 框架,帮助编写实时,交互的应用。

    2015年3月26日 -  Javascript MVC 框架DerbyJS DerbyJS 是一个 MVC 框架,帮助编写实时,交互的应用.

  4. JavaScript基础精华02(函数声明,arguments对象,匿名函数,JS面向对象基础)

    函数声明 JavaScript中声明函数的方式:(无需声明返回值类型) function add(i1, i2) {             return i1 + i2;//如果不写return返回 ...

  5. 用Java开发一个工具类,提供似于js中eval函数功能的eval方法

    今天在看到<Java疯狂讲义>中一个章节习题: 开发一个工具类,该工具类提供一个eval()方法,实现JavaScript中eval()函数的功能--可以动态运行一行或多行程序代码.例如: ...

  6. jQuery 二级菜单,一次显示一个小类 鼠标点击显示小类

    jQuery 二级菜单,一次显示一个小类 鼠标点击显示小类 本例有另外2个关联案例,演示地址分别为2.php,3.php 演示 XML/HTML Code <div class="ar ...

  7. PHP用单例模式实现一个数据库类

    使用单例模式的出发点: 1.php的应用主要在于数据库应用, 所以一个应用中会存在大量的数据库操作, 使用单例模式, 则可以避免大量的new 操作消耗的资源. 2.如果系统中需要有一个类来全局控制某些 ...

  8. 使用代码向一个普通的类注入Spring的实例

    转载请在页首注明作者与原文地址 一:应用场景 什么是普通的类,就是没有@Controller,@Service,@Repository,@Component等注解修饰的类,同时xml文件中,也没有相应 ...

  9. 一个Java文件至多包含一个公共类

    编写一个java源文件时,该源文件又称为编译单元.一个java文件可以包含多个类,但至多包含一个公共类,作为编译时该java文件的公用接口,公共类的名字和源文件的名字要相同,源文件名字的格式为[公共类 ...

随机推荐

  1. Kotlin尝试之一:写代码前的准备

    Kotlin是一种静态类型的编程语言,可在Java虚拟机上运行,也可以编译为JavaScript源代码. 其主要发展来自位于俄罗斯圣彼得堡的JetBrains程序员团队. 虽然语法与Java不兼容,但 ...

  2. 新手如何快速入门Python

    学习任何一门语言都是从入门(1年左右),通过不间断练习达到熟练水准(3到5年),少数人最终能精通语言,成为执牛耳者,他们是金字塔的最顶层.虽然万事开头难,但好的开始是成功的一半,今天这篇文章就来谈谈如 ...

  3. Android React Native 开发环境搭建---windows下

    环境搭建 环境搭建可以参考RN官网,也可以参考中文版本:http://reactnative.cn/docs/0.45/getting-started.html 如果你希望可以看到原版的安装流程,可以 ...

  4. sqlserver 游标写法

    1.简单游标 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 declare m_cursor cursor scroll for select  Address,People ...

  5. (转)关于BigDecimal 转化字符串toPlainString()和toString()的区别

    对于  BigDecimal b ;     (b=(0.4321)^ 20)String s = b.toPlainString() ;System.out.println(s) ; 输出为:0.0 ...

  6. 浅谈java内存分配和回收策略

    一.导论 java技术体系中所提到的内存自动化管理归根结底就是内存的分配与回收两个问题,之前已经和大家谈过java回收的相关知识,今天来和大家聊聊java对象的在内存中的分配.通俗的讲,对象的内存分配 ...

  7. Nginx学习笔记1-Nginx功能模块以及进程管理

    1.         功能 1.1.           功能描述 使用缓存加速反向代理,简单负载均衡和容错: 使用缓存机制加速远程FastCGI服务器的访问: 模块化结构: 基本的HTTP功能: 邮 ...

  8. WPF Dashboard仪表盘控件的实现

    1.确定控件应该继承的基类 从表面上看,目前WPF自带常用控件中,没有一个是接近这个表盘控件的,但将该控件拆分就能够发现,该控件的每个子部分都是在WPF中存在的,因此我们需要将各个子控件组合才能形成这 ...

  9. [USACO08JAN]手机网络Cell Phone Network

    [USACO08JAN]手机网络Cell Phone Network 题目描述 Farmer John has decided to give each of his cows a cell phon ...

  10. 将逗号分隔 的字符串转化成List

    将逗号分隔 的字符串转化成List List<String> parIdListTmp = new ArrayList<String>(); String parIdArray ...