close
当前位置: 物联网在线 > 技术文库 > android >

写给Android/Java开发者的JavaScript精解(2)

Java和JavaScript最不一样的地方是什么?我觉得是函数!在Java中,函数(也称为方法)是对象的一部分,一般是通过对象调用函数。在JavaScript中,函数已经和对象平起平坐,函数是独立于对象的,甚至可以用来创建对象。因此,从Java转学JavaScript时,应时刻注意不要将Java中对象和函数的概念生搬硬套到JavaScript中,这是学好JavaScript的关键。

五、在JavaScript中,对象能继承吗?

在Java中,继承通常指的是类之间、接口之间的一种关系,所谓A类继承B类,是指A类中可以直接使用B类中的非private的字段和方法,就像A类中本来就有这些字段和方法一样。

在JavaScript中,没有对应于Java的类、接口的概念,但是却有继承的概念。只是这里的继承指的是对象之间的一种关系。对象A继承对象B,指的是对象A可以直接使用对象B中的属性,就想对象A本身就有这些属性一样。

1、对象继承的实现原理

由于JavaScript中的对象只有键值对,所以实现对象之间的继承很自然地也要使用这一特性。

在任意一个JavaScript对象a中,都有一个属性叫做"__proto__"(注意:这里proto两侧各是两条短下划线),这个属性的值是另一个对象b,它被称为对象A的原型(即proto一词的含义)。此时,对象a可以将对象b中的属性当作自己的来使用。举例如下:
var b ={ prop_of_b : "property of b" }; var a = {__proto__ : b } ;
上面代码中,我们将对象a的原型设置为对象b,此时我们可以这样使用:

a.prop_of_b //值为 property of b

对象a的原型为对象b,也可以称为对象a继承对象b,只是这种继承不再是Java中的继承了,它叫做基于原型的继承(我们把它简称为原型继承)。

2、原型继承中的属性屏蔽

好的,现在问题来了,假如我们在a中定义一个与对象b中同名的属性会怎样呢?如下所示:

a.prop_of_b = ' own property of a' ;

此时,如果在程序中再访问a.prop_of_b,它的值是什么呢?答案是:own property of a
这里,要引入一个新的概念,叫做对象的自有属性(own property),简单讲,它指的是那些对象自己拥有的,不是继承自原型的属性。

当我们使用圆点语法(object.prop)去获取一个对象的属性值时,JavaScript引擎首先在对象的自有属性中查找,一旦找到,就直接返回该自有属性的值,只有当自有属性中没有要访问的属性时,才会去对象的原型中查找它的自有属性。

回到上面的例子,a已经有了一个自有属性prop_of_b,所以访问a.prop_of_b时就直接返回了该自有属性的值 ' own property of a',而没有去它的原型b中查找属性prop_of_b。

所以,当对象的自有属性与原型对象中的属性同名时,会屏蔽原型对象中的同名属性。这种特性很像Java中的覆写(override)。

3、原型继承中的原型链

进一步思考,我们可能会问,假如我们访问的对象属性既不是对象的自有属性,也不是原型对象的自有属性,JavaScript会怎么处理我们的访问请求呢?比如我这样写:

a.notExistProperty 。

这里,又要引入一个新的概念:原型链

很简单,对象a的原型是b,对象b也会有一个原型c,对象c还会有一个原型d,对象d还会有......
这很自然地形成了一个原型链,链的尽头是什么?答案是一个很特殊很重要的对象:Object.prototype

原型链尽头的对象,就是Object的属性prototype所指向的对象。我们在上篇文章开头已经用到了Object对象,我们用它来创建了一个新的对象(new Object(),记得吧?),现在,我们对它有了新的认识,它的prototype属性所指向的对象是所有对象原型链的最后一站。

如果你非要问对象Object.prototype难道没有__proto__属性?如果有,这个属性值是什么?
答案是:有!但它的值是null。好了,你好奇心是不是得到了极大满足?

明白了原型链,我们再来看JavaScript引擎如何处理
a.notExistProperty
首先,引擎查找a的自有属性,没找到notExistProperty,
然后查找其原型b的自有属性,也没有找到notExistProperty,
然后查找b的原型的自有属性......
就这样一级一级往上找,
最后找到了Object.prototype,发现它也没有属性notExistProperty,于是JavaScript返回值 undefined,表示这个属性未定义。

4、使用原型继承的一些便利方法

对象Object和对象Object.prototype中有一些方法,为大家使用原型带来了很大便利。如Object.prototype有一个方法hasOwnProperty可以用来判断一个属性是不是对象的自有属性。上例中,我们给b增加一个新的属性:
b.prop1 = 'prop1' ;

虽然,我们可以通过a.prop1来获取'prop1',但我们可以判断出来prop1并不是a的自有属性,方法如下:
a.hasOwnProperty('prop1') ; //值为 false

注:使用这个方法时,属性字符串必须加上单引号或双引号

这里有一个问题,为什么我们可以直接在对象a上调用方法hasOwnProperty呢?这个方法不是Object.prototype所有的吗?


(责任编辑:ioter)

用户喜欢...

Android Weekly #276 安卓开发周刊 中文版

您是否了解过Android的Lifecycle-Aware库?(android.jlelse.eu) 我们如何了解Lifecycle-Aware库代码? Nishant Srivastava展示了可以跟踪活动或Lifecycle-Aware的Lifecycle Arch组件的片段,并相应地调整其行为。 为Mos...


Android Weekly #275 安卓开发周刊 中文版

MapMe — Android地图适配器 (medium.com) Josh Burton介绍MapMe,是一个用Kotlin编写的Android库,可以将适配器模式带到地图上。 赞助 CloudRail - 连接到API 10x更快 (cloudrail.com) 当我们用单一的界面连接到所...


使用Android Studio开发可独立运行(runnable)混淆过的Jar程序

之前开发Java程序一直都是使用Eclipse 开发Jar程序,现在开发基本上都已经弃用Eclipse了,但是有时偶尔开发个小的Jar程序,还要切换回去好麻烦,刚好前几天有人问几个相关的问题,就顺便整...


Android Weekly #274 安卓开发周刊 中文版

探索Android Oreo上的别后执行限制(medium.com) 在这篇文章中,Joe Birch解释了关于Android Oreo在后台运行服务的变化。 non-Time领主的time – 第5部分 (blog.stylingandroid.com) Mark Allison继续分析JSR 310 date和...


Android Weekly #273 安卓开发周刊 中文版

开源你的Android代码(android.jlelse.eu) 通过您的开源Android代码,您将(希望地)为Android社区提供有价值的代码,收到建设性的反馈,并与您最初建立的内容进行协作从而使您的代码变得更好。这...


Android Weekly #272 安卓开发周刊 中文版

Android Dev 101:每个初学者都应该知道的一些做法() 看一些初学者或媒介等级开发人员(不要错过任何人)应该知道的一些做法,以便更好地摆脱Android框架。 99.9% crash free sessions (medium.com) Chr...


Android Weekly #271 安卓开发周刊 中文版

依赖注入检查(medium.com) 在本文中,MihályNagy引入了依赖注入检查,一种开源注释处理器,可帮助您解决一些出现在所有JSR 330 DI库中常见的问题。 使用Android Studio插件提高效率 (blog.mindorks.com...


Android Weekly #270 安卓开发周刊 中文版

带有RxJava2的SOLID Android分析 (medium.com) 在这篇文章中,Aris Papadopoulos将解释如何正确创建一个分析系统,同时遵循SOLID原则,并使用RxJava2来解决问题。 (blog.stylingandroid.com) Java中的编程时间很难...


Android内存泄漏思考

Android内存泄漏是一个经常要遇到的问题,程序在内存泄漏的时候很容易导致OOM的发生。那么如何查找内存泄漏和避免内存泄漏就是需要知晓的一个问题,首先我们需要知道一些基础知识。...


Android Weekly #269 安卓开发周刊 中文版

在Google上快速提出操作 () Wolfram Rittmeyer分享了开始在Google上快速创建操作所需的所有信息(为了家庭与助理)。 RxJava中的错误处理(rongi.github.io) 一旦开始编写RxJava代码,你就会意识到有些事...