当前位置: 首页 > 科技观察

JavaScript王国之旅,没有类的世界如何玩转面向对象?

时间:2023-03-12 13:03:57 科技观察

1。前言作为Java帝国未来的继承人,Java小王子接受过严格的教育,不仅精通Java语言、Java虚拟机、Java类库和框架,还熟悉各种Java官方规范。最近听说有个叫Javascript的屌丝逆袭成功建立了独立王国。他不仅成为了前端编程之王,还在不断蚕食着Java帝国的版图!按照小王子宫师的说法:这家伙只在浏览器里跑,完全是看Java流行才开发的。现在他转身要欺负我们。有什么理由吗?是可以忍还是不能忍?!小王子不是那样的他认为存在一定是合理的,javascrip一定有它的独特之处。俗话说知己知彼方能百战百胜。他觉得有必要去Javascript王国窥探一下,搜集资料,看看这个曾经的浏览器中面向对象的语言是怎么回来的。为什么那么多码农趋之若鹜。2.初步印象小王子打扮好后来到了Javascript王国。看起来热闹非凡。人随性洒脱,不像爪哇帝国那样严肃死板,让人心情愉悦。不过让小王子觉得不可思议的是,这里竟然没有官方的类库!人们在工作中使用了五花八门的工具,让人眼花缭乱,AngularJS、React、Backbone、Vue、Ember、JQuery、……彼此之间还吵着吵着,吵得不可开交,热闹非凡。相比之下,Java帝国有着严苛的规矩,政府提供的庞大的类库,以及世界领先的Web框架SSH/SSM,再加上各种Java规范,coder们只需要用它来学习,工作就可以了。没有了选择的烦恼,但同时也减少了选择的权利。是好还是坏?小王子自己也不知道。小王子还注意到,在Javascript王国里写程序的几乎没有人使用IDE。随便找一个好用的文本编辑器开始工作,然后扔进浏览器运行测试。真的很轻!IntelliJIDEA和Eclipse的优势真的不用争论。3.如何创建没有类的对象?随着调查的深入,小王子越来越吃惊。这里没有类的概念!面向对象的语言没有类!这违背了小王子从小被灌输的观念!如何创建没有类的对象?小时候法院老师常说:先写一个类,然后从这个类创建一个对象。但是摆在我们面前的javascript对象数不胜数。他们不断地出生和死亡,共同努力支撑着一个庞大而充满活力的帝国。这些物体是从哪里来的?小王子想不通。中午的时候,小王子看到面前是一家json酒馆,便决定好好休息一下,好好吃饭再说话。小皇子点了两斤熟牛肉和三碗酒,刚要享用,就听邻桌一个长袍人问道:“咦,你说的物体原型是什么?”?另一个戴眼镜的人随后低声说道:嘘,不要出声,国王刚刚下达命令,原型法是我帝国的机密,禁止公开讨论,以防被爪哇帝国得知。小皇子心中一动,连忙把小二叫了过来,要了上等的酒菜,送到隔壁桌,请两人喝酒。喝了很多之后酒后,小王子终于赢得了两人最初的信任,原来他们还是负责审查javscript语言规范的官员。小王子问:“我家世代经商,云游四方,走遍了C++王国、Java帝国、C#帝国,都是所谓的面向对象语言,都有”戴眼镜的官员说:“我们不用类,太不直观了!”小王子暗自纳闷,仔细一想,好像是这样的,记得当初学Java的时候,费了好大劲才接受类的概念,其实不是对象面向系统只是对象之间的交互?要类干什么?然后小王子问了一个关键问题:“没有类怎么创建对象啊”“外行,没那么复杂,想想一个对象是什么?”是啊,不就是属性加方法吗? 看看我们,创建一个对象。这位负责人说着,伸手指着桌子上写着饮料:你看,这个动物对象定义了一个属性名,一个方法eat,是不是很简单?”确实简单明了,根本不需要class,创建了一个对象,在小王子面前仿佛打开了一扇新的大门。还这么玩?!”小王子一惊,没有类4.没有类怎么继承?“那怎么实现继承?继承是面向对象的一个??重要概念。”眼镜负责人说:“很简单,继承不就是建立两个对象之间的关系吗?出色地!在我们的javascript王国里,每一个对象都有一个特殊的属性,叫做__proto__,你可以通过这个属性来关联另一个对象(这个对象就是所谓的原型),我给你画一段吧,写的代码不长,但是它深深震惊了小王子,因为其中的信息量巨大,而且隐藏着“原型”的秘密,小王子不禁陷入了沉思:对象狗的原型是动物(注:也是一个对象),对象猫的原型也是动物。不管是dog还是cat,都没有定义eat()方法,怎么调用呢?调用eat方法时,先在自己的方法列表中查找,如果找不到,再到原型中的方法中查找,如果在原型中找不到,则到原型中查找找到它的原型......***FindObject,如果你仍然找不到它,它是未定义的。这里的这些对象肯定是通过__proto__建立了原型链!嗯,我师父给我讲JVM虚拟机的时候,也提到了对象执行方法的时候,需要找到方法的定义。这个查找的顺序也是从对象所属的类开始,然后是父类,然后是父类的父类……直到Object,思路是一模一样的!只不过Java的方法定义是在类中,而这个javascript方法是在对象中,现在觉得在对象中更直观。属性和方法应该是类似的,顺着原型链往上看,但是这里dog的name属性好像覆盖了animal的name属性,调用dog.eat()时的this应该指向dog的对象.好像想通了面向对象的概念。想着想着,小皇子的脸上露出了笑容。见小皇子像程序卡住了一样一动不动,长袍官推了推小皇子:陌生人,你怎么了?小王子意识到自己失态了,连忙说道:“哦,没什么,我觉得你用的‘原型’方法很巧妙,完全不用类就实现了继承。”眼镜官愣了愣:“外域人,看来你的悟性不错,还洞察了帝国的秘密,不过有很多新手程序员不太容易理解这一点,所以我们做了一个变通办法,让javascript可以像Java一样创建新的对象。说来惭愧,这完全是为了迁就那些C++、Java、C#程序员5.小王子找Java说:“Whatworkaround?你也开始使用类了吗?”“不,我们提供了一种叫做构造函数的东西。我还是给你写点代码吧。”负责人说着,蘸了点饮料开始写:“这个函数看起来已经是一个类了,我的天,对了,我看到关键字this了。Student是故意大写的吗?”“是的,所以它看起来像一个Java类。但是,中间有个问题,你看到了吗?”小王子想了想:“是不是说每一个新创建的对象都有一个sayHello函数?在Java中,函数是在类上定义的。如果定义在对象上,就意味着每个对象都有一个副本,太浪费了。”“是的,所以我们要提供一种更高效的方式,把这个sayHello函数放在另外一个地方!”“放在哪里?”“还记得我们刚才说的原型链吗?当一个对象调用一个方法的时候,我们会向上查找这个链,所以我们可以创建一个原型对象,其中包含sayHello函数,让从Student创建的对象,比如andy和lisa,指向这个原型并一切都会安好的。”“可是你这里只有构造函数Student,你在哪里创建原型对象呢?怎么把andy和lisa对象的__proto__指向原型对象呢?我不会让我手动指定它。眼镜官瞪了小王子一眼说道:“我们的javascript帝国肯定不会这么麻烦程序员的,我们可以把这个原型对象放在Student里面。当你第一次创建像andy和lisa这样的对象时,javascript会自动建立原型链!”小王子一脸尴尬:“哎呀,这个有点难懂。”“画个图吧。当你去到NewStudent的时候,javascript会建立这样一个关系链:”小王子说:“明白了,这个所谓的构造函数Student其实就是一个套子,每次去到NewStudent,它确实会创建一个对象(andyorlisa),并将这个对象的原型(__proto__)指向Student.prototype对象,这样就可以找到sayHello()方法。眼镜官回复道:“对啊,这个地方容易混淆的两个属性就是__proto__和prototype,唉,我也不知道当初为什么要这么做,真是不优雅。””“是的,这个构造函数加上原型的概念,实在是让人费解,所以我们讨论了提供一点语法糖,减轻程序员的负担。长袍官员附和道。6.语法糖听到语法糖,小王子觉得很亲切,因为Java也提供了很多方便程序员使用的语法糖。当袍官给javascript写语法糖的时候,小王子不禁吃惊:这种语法糖竟然让javascript和Java、C#、C++类非常相似。看来javascript帝国为了“取悦”程序员一直在努力改变它。看来我们的java帝国要努力了。小王子现在明白了,Javascript是一门基于原型的面向对象语言。根本没有阶级的概念。新方法对小王子的思维观念带来了重大影响。在这里呆久了,他也了解到javascript的强大。函数式编程,越来越喜欢javascript了,有点舍不得离开。小王子会回到爪哇帝国吗?【本文为专栏作家“刘欣”原创稿件,转载请通过作者微信公众号coderising申请授权】点此阅读更多本作者好文