JavaScript学习之旅-12( 原创 )-阿里云开发者社区

开发者社区> 开发与运维> 正文
登录阅读全文

JavaScript学习之旅-12( 原创 )

简介: 在上一篇文章中,主要学习了JavaScript中的Date对象、正则表达式、Json、浏览器对象。这一篇我们主要深入学习探索JavaScript中的对象以及构造函数的说明和使用。

上一篇文章中,主要学习了JavaScript中的Date对象、正则表达式、Json、浏览器对象。这一篇我们主要深入学习探索JavaScript中的对象以及构造函数的说明和使用。

我们知道,在Java这门面向对象建模的计算机语言中,创建对象(新建一个Class,肯定是直接或者间接继承Object)、创建完毕之后接着使用对象(使用对象内部封装的函数完成开发需求,也就是new 对象,使用对象内的方法,也称对象的实例)是这们语言的灵魂和基础。不过,在JavaScript中,这个概念需要改一改。JavaScript不区分类和实例的概念,而是通过原型(prototype)来实现面向对象编程。实际上JavaScript对每个创建的对象都会设置一个原型去指向它的原型对象。

继承,是Java这门语言的特征之一,子类继承父类的目的是,子类可以吸收父类的数据属性和行为,并能扩展新的能力。那么,在JavaScript中,也有一种类似继承拓展的能力,我们首先定义一个对象:


img_35cd5eb101b46c32bcd1c4ed01da2ab0.png
定义一个“父类”

假设我现在想和Java一样,想实现类似继承的功能,这个该如何去做?这个时候,我们可以首先定义一个对象,然后使用关键字  __proto__ 去完成操作,写法如下:


img_603b44e9fc360f3dc0d4b102a13858ec.png
“继承”

其中,红色的矩形为写法以及关键字,蓝色箭头代表“父类”,然后测试下结果:


img_37b9f5e8f34cfc34252a41b612948643.png
结果

可以看到,我们使用关键字 __proto__  之后,红色矩形内的名字以及成功被我们修改成 Tom 了,且 newCooker对象也成功使用了“父类”里面的play字段的函数。

但是一般不要直接用obj.__proto__去改变一个对象的原型,并且,低版本的IE也无法使用__proto__。解决办法如下:可以使用Object.create()方法,这个方法可以传入一个原型对象,并创建一个基于该原型的新对象,但是新对象什么属性都没有,因此,我们可以编写一个函数来创建想要“继承父类的子类”。

那么我们把上面的代码用函数返回对象的方式改一下,就有了以下的代码:

img_32311a6007a343292962c36eed694719.png
使用函数“继承”

关于继承的这一特点,会在下面的一篇文章专门讲述。

概念一:向上查找

我们首先复习回顾下JavaScript中对象的基本写法:


img_4a794608965a2d022c56ac0de7a4e36f.png
JavaScript对象基本写法

获取对象内的属性值,我们知道是用 obj.xxx 去获取一个对象的属性。那么这个获取对象属性值的操作是如何执行的?JavaScript首先在当前对象上查找该属性,找到了该属性值就返回,如果没有找到,就到其原型对象上一级找。如果还没有找到,就一直向上直到Object.prototype对象。

如果Object也没有找到,就返回undefined。

别忘了,JavaScript中,函数也是一个对象。这个跟Java有很大的差别(因为Java中函数的返回值可以是void)。所以,JavaScript首先在当前函数对象上查找该属性,找到了该属性值就返回,如果没有找到,就到其原型对象上一级(也就是Function.prototype)找。如果还没有找到,就一直向上直到Object.prototype对象。

如果Object也没有找到,就返回undefined。

所以,函数对象和普通对象的执行顺序都是一样的,自己要是没有就向上找,如果上层也没有这个对应的属性,就会undefined。

概念二:构造函数

我们知道,Java的构造函数主要作用是完成对象的初始化工作,它能够把定义对象时的参数传给对象的域。那么,JavaScript中的构造函数是什么?

JavaScript可以用构造函数的方法来创建对象。它的用法如下:


img_a41fd756f088eb127137afe271743a92.png

首先这是一个普通函数,但是在JavaScript中可以使用关键字new来调用这个函数,并返回一个对象(按照约定,构造函数首字母应当大写,而普通函数首字母应当小写,这里为了展示方便就用小写,后面还是需要严格按照书写规范进行书写)。如果不写new,这就是一个普通函数,它返回undefined。但是,如果写了new,它就变成了一个构造函数。


img_2e5829639c68ce28fcba2cf1020a8da8.png
构造参数

用new 函数()创建的对象,理论上从原型上获得了一个constructor属性,它指向函数本身(这里就是 constructorFun )


img_877cad1aec695ace310edfc5e4eb9851.png

通过实践得知,构造函数的constructor属性原则是一样的。

还有一种情况:

如果我们通过new 构造函数创建了很多对象,这些对象的内部函数实际上只需要共享同一个函数就可以了,这样可以节省很多内存。

要让创建的对象共享公共的函数,根据对象的属性查找原则,我们只要把公共函数移动到new 出来的对象上一层就可以了(Java中叫抽取公共代码放到父类,也可以用构造代码块去实现),那么上面的代码我们可以改成这样:


img_d828db8147c58cda894ff3e30b87566d.png
抽取公共的方法

构造函数的进阶用法:

如果一个函数被定义为用构造函数去创建对象,但是使用时我们忘记了写 new 怎么办?

为了规避这种情况,我们可以从书写规范去入手,上面也提到过构造函数首字母应当大写,而普通函数首字母应当小写。然后还有一种比较好的方式,就是参考Java中的做法,将实例化对象的操作,放在一个函数里面,这样通过调用这个函数就可以间接的给我们完成new对象的工作了。代码如下


img_29aa5726b890232e4b62483768942c34.png

首先,蓝色方框内,是一个构造函数,里面是具体的属性

然后我们把new对象的过程放在了图中的红色方框,

绿色方框就是调用new对象的函数,将参数传递进去,完成赋值操作,然后打印。

这样写的函数有以下优点:一是不需要new来调用,二是参数非常灵活,可以不传也可以传。当然也比较推荐这种写法。

本篇文章主要学习的是关于对象的深入分析以及构造函数的说明和使用。本章的基本内容就结束了。

未完待续。。。

如果这篇文章对你有帮助,希望各位看官留下宝贵的star,谢谢。

Ps:著作权归作者所有,转载请注明作者, 商业转载请联系作者获得授权,非商业转载请注明出处(开头或结尾请添加转载出处,添加原文url地址),文章请勿滥用,也希望大家尊重笔者的劳动成果。

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

分享:
开发与运维
使用钉钉扫一扫加入圈子
+ 订阅

集结各类场景实战经验,助你开发运维畅行无忧

其他文章
最新文章
相关文章