为什么说JavaScript是面向对象的语言

“面向对象”和“基于对象”两个词在 JavaScript 多个版本的标准中反复出现,那么为什么说他是面向对象,他和类似于 JAVA 这样的语言都是面向对象,这两个之间有什么区别呢,为什么会给人截然不同的感觉?甚至有的说法是JavaScript不是面向对象。

一 对象

先来解释下【对象】这个词,对象Object是一切事物的总称,是符合人类思维抽象的一个产物,不是计算机领域凭空捏造的。在《面向对象分析与设计》这本书中描述人类认知角度的对象:

  1.     一个可以触摸或者可以看见的东西
  2.     人的智力可以理解的东西
  3.     可以指导思考或行动(进行想象或施加动作)的东西

上述是对象的自然定义,下面来描述编程中的对象。在不同的编程语言中,设计者也利用各种不同的语言特性来抽象描述对象,最成功的流派是使用“类”的方式来描述对象,如C++, Java等,而JavaScript的设计者选择通过“原型”的方式来解释对象(题外:不幸的是由于诞生之初的政治原因,JavaScrip被要求模仿Java,所以设计者在原型运行时的基础上添加了[[class]],new,this等语言特性,使之看起来更像Java。这使得在ES6出现之前,大量的程序员试图在原型体系的基础上,把JavaScript变得更像是基于类的变成语言,所以你懂的,强扭的瓜不甜,产生了一些怪异的框架。ES6其实是统一了“类”在JavaScript中的使用标准,也是以上的“不幸”才会造成许多程序员感觉混乱的原因)。

 JavaScript 对象模型

说了一堆,抛开上述的历史的“不幸因素”,进入正题,看看JavaScript是如何设计对象模型的(从这里开始暂时抛开类的概念)。

对象的基本属性:

1.    唯一标识性
一般的展现形式就是在系统中有唯一的内存地址,这个大部分语言都是一样的,对象具有唯一标记的内存地址

2.    状态
对象有状态,状态可以改变

3.    行为
行为改变也会改变对象的状态

第一个就不多说了,JS的内存机制了解下。至于状态和行为,不同语言会用不同的术语来抽象描述他们,如C++称为“成员变量”和“成员函数”,Java称“属性”和“方法”,JavaScript中统一抽象为“属性”(普通属性和函数对于JavaScript来说,是一视同仁的),如果你使用Java,一定不要觉得奇怪,尽管设计思路有一定差别,但是二者都很好的表现了对象的基本特征:标识性,状态和行为。

下面来说说JavaScript 中的“ 属性 ”。JavaScript中的属性可不是简单的属性名+属性值,属性分为两种类型:数据属性和访问器属性。

(一)数据属性

        通常我们定义属性的代码会产生数据属性,4个特征:

        1.    value:属性值,大多数情况下,我们只需要关注属性的值即可

        2.    writable:属性是否可以被赋值,默认true

        3.    enumerable:for in能否枚举该属性,默认true

        4.    configurable:属性能否被删除或改变特征,默认true

(二)访问器属性

访问器属性使得属性在读和写的时候执行代码,允许使用者在读和写属性的时,得到完全不同的值。4个特征:

1.    getter:函数或undefind,在取属性值时被调用

2.    setter:函数或undefind,设置属性值时被调用

3.    enumerable:for in能否枚举该属性,默认true

4.    configurable:属性能否被删除或改变特征,默认true

    下面来了解下怎么通过操作这些特征来控制属性。

    1)可以使用内置函数getOwnPropertyDescripter来查看属性的特征,可以运行下面的代码试试:

var o = {a: 1};
 
o.b = 2;
 
// a和b都是数据属性
 
Object.getOwnPropertyDescripter(o.a);
 
Object.getOwnPropertyDescripter(o.b);

   2)如果想要改变属性的特征,可以使用defineProperty, 可以运行下面的代码试试:

var o = {a: 1};
 
Object.defineProperty(o, ‘b’, {value: ‘2’,writable: true, enumerable: false, configurable: false});
 
// a和b都是数据属性
 
Object.getOwnPropertyDescripter(o.a);
 
Object.getOwnPropertyDescripter(o.b);

3)创建对象时,可以使用get和set关键字来创建访问器属性,可以运行下面的代码试试:

var o = {get a() { return 1 }};
 
console.log(o.a);

 

 访问器属性和数据属性有所不同,每次访问器属性都会执行getter和setter函数。这里getter返回了1,所以每次访问o.a都会得到1。

        实际上,JavaScript 对象的运行时就是一个“属性的集合”,属性以字符串或者Symbol为key,以数据数据属性特征值或者访问器属性特征值为value(能够以Symbol为属性名,这是JavaScript对象的一个特色)。

        讲到这里,我们就解释了开头说到JavaScript是面向对象,也可以理解为什么会有“JavaScript不是面向对象”的说法,这是由于JavaScript的对象设计和目前主流基于类的面向对象差异非常大。实际上,虽然这样的设计特别,但是JavaScript提供了完全运行时的对象系统,这使得它可以模仿多数面向对象编程范式(基于类和基于原型),所以,划重点,她也是 正统的面向对象语言。(再遇到有人像开篇那样说,就用今天讲的呼到他脸上,标准爸爸的结论也敢质疑???不懂就不要乱说好伐!!!)

        所以,我们应该在理解其设计思想的基础上充分挖掘她的能力,而不是机械的模仿其他语言。

        最后,介绍一个JavaScript中对象独有的特色,对象具有高度的动态性(别家都羡慕不来)——既JavaScript的高度动态性的对象系统。简单解释这是因为,JavaScript赋予了使用者在运行时为对象添改状态和行为的能力(开发的时候切身感受一下)

        总结一下,对象的解释有多种方式,都是好猫(就好比资本主义和共产主义),不同语言有不同的“对象观”,在学习的过程中,不可以带着有色眼镜去看待问题,不然最后的结果就是“剪不断理还乱”了。

        还是有同学会疑惑,于是产生了灵魂三问:

        1.     既然JavaScript是通过原型面向对象的,那为何ES6中还会有类的概念,这不是和上面说的矛盾了吗?

        2.     要是原型也可以满足面向对象,还要类的概念做什么呢,不会是JavaScript也跟风了吧,要把前端后端化?

        3.     JavaScript的特色使用仅仅是运行时赋值这么简单吗,JavaScript如何基于动态对象模型设计自己的原型系统的呢?

        学习的过程中就像是理毛线团,有很多头绪,解释了开篇的本源问题,其他的问题是今天挖下的坑,感兴趣可以顺藤摸瓜自己先了解,后面继续解惑。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

DoubleNa

客官常来,谢谢客官抬爱

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值