木灵鱼儿
阅读:2862
Javascript对象是面向对象还是基于对象
什么是面向对象?
不同的语言,他们对于对象的解释都不相同,但无论如何,我们应该认识到,对象并不是只存在于计算机领域的一个概念,它是顺应人类思维模式产生的一种抽象。
那么,我们先来了解下人类思维模式下,对象是什么?
对象这一概念在人类的幼儿期形成,这远远早于我们编程逻辑中常用的值、过程等概念。在幼年期,我们总是先认识到某一个苹果能吃(这里的某一个苹果就是一个对象),继而认识到所有的苹果都可以吃(这里的所有苹果,就是一个类),再到后来我们才能意识到三个苹果和三个梨之间的联系,进而产生数字“3”(值)的概念
在《面向对象分析与设计》这本书中,Grady Booch替我们做了总结,他认为,从人类的认知角度来说,对
象应该是下列事物之一:
- 一个可以触摸或者可以看见的东西;
- 人的智力可以理解的东西;
- 可以指导思考或行动(进行想象或施加动作)的东西
有了对象的自然定义后,我们就可以描述编程语言中的对象了。在不同的编程语言中,设计者也利用各种不
同的语言特性来抽象描述对象,最为成功的流派是使用“类”的方式来描述对象,这诞生了诸如 C++、Java
等流行的编程语言
而 JavaScript 早年却选择了一个更为冷门的方式:原型
Javascript 对象特征
在我看来,不论我们使用什么样的编程语言,我们都先应该去理解对象的本质特征(参考GrandyBooch《面向对象分析与设计》)。总结来看,对象有如下几个特点。
- 对象具有唯一标识性:即使完全相同的两个对象,也并非同一个对象。
- 对象有状态:对象具有状态,同一对象可能处于不同状态之下。
- 对象具有行为:即对象的状态,可能因为它的行为产生变
对象具有唯一标识性
在js中,对象的唯一标识就是他在内存中的地址,因此我们知道,即便两个对象的内容相同,但是他们也不是相同的。
var o1 = { a: 1 };
var o2 = { a: 1 };
console.log(o1 == o2); // false
对象有状态和对象具有行为
在javascript中,模糊了状态和行为,他们统称为:属性;所以 JavaScript中的行为和状态都能用属性来
抽象。
var o = {
d: 1,
f() {
console.log(this.d);
}
}
在o对象中,d是一个属性,f也是一个属性,虽然他们两的写法不同,但是对JavaScript来说,d和f就是两个普通属性。
所以,总结一句话来看,在JavaScript中,对象的状态和行为其实都被抽象为了属性。如果你用过Java,一定不要觉得奇怪,尽管设计思路有一定差别,但是二者都很好地表现了对象的基本特征:标识性、状态和行为。
在实现了对象基本特征的基础上,我认为,JavaScript中对象独有的特色是:对象具有高度的动态性,这是因为JavaScript赋予了使用者在运行时为对象添改状态和行为的能力。
var o = {a:1};
o.b=2;
console.log(o.a,o.b); //1,2
o被声明后就已经运行了,运行后我们还给他添加了b属性,这就是运行时为对象添改状态和行为的能力。
Javascript对象的两类属性
对JavaScript来说,属性并非只是简单的名称和值,JavaScript用一组特征(attribute)来描述属性(property)。
先来说第一类属性,数据属性。它比较接近于其它语言的属性概念。数据属性具有四个特征:
- value:就是属性的值
- writable:决定属性能否被赋值
- enumerable:决定for in能否枚举该属性
- configurable:决定该属性能否被删除或者改变特征值
在大多数情况下,我们只关心数据属性的值即可
第二类属性是访问器(getter/setter)属性,它也有四个特征:
- getter:函数或undefined,在取属性值时被调用
- setter:函数或undefined,在设置属性值时被调用
- enumerable:决定for in能否枚举该属性
- configurable:决定该属性能否被删除或者改变特征值
访问器属性使得属性值在读写时得到完全不同的值。
我们通常用于定义属性的代码会产生数据属性,其中的writable、enumerable、configurable都默认为true。我们可以使用内置函数 Object.getOwnPropertyDescripter来查看,如以下代码所示:
var o = { a: 1 };
o.b = 2;
//a和b皆为数据属性
Object.getOwnPropertyDescriptor(o,"a");
//{value: 1, writable: true, enumerable: true,configurable:true}
Object.getOwnPropertyDescriptor(o,"b");
//{value: 2, writable: true, enumerable: true,configurable:true}
如果我们要想改变属性的特征,或者定义访问器属性,我们可以使用 Object.defineProperty,示例如下:
var o = { a: 1 };
//修改
Object.defineProperty(o, "b", {value: 2, writable: false, enumerable: false, configurable: true});
//获取
Object.getOwnPropertyDescriptor(o,"a");
//{value: 1, writable: true, enumerable: true,configurable:true}
Object.getOwnPropertyDescriptor(o,"b");
//{value: 2, writable: false, enumerable: false,configurable:true}
//我们定义b属性设置为是不能被修改的
o.b = 3;
console.log(o.b); //2
在创建对象时,也可以使用 get 和 set 关键字来创建访问器属性,代码如下所示:
var o = {
get a() { return 1 }
};
console.log(o.a); //1
访问器属性跟数据属性不同,每次访问属性都会执行getter或者setter函数。
这里我们的getter函数返回了1,所以o.a每次都得到1。
这样,我们就理解了,实际上JavaScript 对象的运行时是一个“属性的集合”,属性以字符串或者Symbol为key,以数据属性特征值或者访问器属性特征值为valu
对象是一个属性的索引结构(索引结构是一类常见的数据结构,我们可以把它理解为一个能够以比较快的速
度用key来查找value的字典)。我们以上面的对象o为例,你可以想象一下“a”是key
{writable:true,value:1,configurable:true,enumerable:true}是value。我们在前面的类型课程中,已经介绍了Symbol类型,能够以Symbol为属性名,这是JavaScript对象的一个特色。
到这里,我们可以知道,javascript的面向对象和目前主流的基于类的面向对象差异非常大。
但是它就是面向对象的语言。
版权申明
本文系作者 @木灵鱼儿 原创发布在木灵鱼儿 - 有梦就能远航站点。未经许可,禁止转载。

相关推荐
什么是面向对象与设计模式
面向对象对于面向对象的理解,千人千面,不同的人有不同的解读,这里就以我个人所了解的知识给大家解释一下面向对象。历史角度我们先从历史的角度去看!计算器在发明之初,处理的能力是有限的,所有的代码编辑都需要根据“机器语言(二进制)”来进行编写。这显然非常痛苦。那么如果我们把二进制换成一个个单词(助记符单词),是不是又更好一点了呢,于是“汇编语言”诞生了,但是使用上也就被机器语言强那么一点点。那么有没有比汇编语言更好用的呢?于是面向过程的C语言出现了,c的位置处于机器与人的中间点,既没有偏向人的思维模式,也没有偏向机器语言思维。可以说c语言的底层结构是机器语言,但是它将机器语言封装成自己的语法,...

JavaScript类型:关于类型,有哪些你不知道的细节?
Undefined 为什么有的编程规范要求用void 0代替undefined?因为在js里面,undefined是一个变量,它奴属于window,是全局对象window的一个属性。但是全局的undefined是无法被修改的,这也意味着在局部作用域中我们可以重新定义undefined变量function test() { var undefined = "我被重新定义了"; const a = undefined; console.log(a); } test(); //我被重新定义了这种情况只有在我们直接使用undefined变量的时候才会出现。...
杰哥
Google Chrome Windows 10作者最近是看了什么书啊
木灵鱼儿
FireFox Windows 10???咋了
杰哥
Google Chrome Windows 10想学习一下,我刚刚看到你的tag是【重学前端】以外是一本书
杰哥
Google Chrome Windows 10看到你的tag是【重学前端】以为是一本书
木灵鱼儿
FireFox Windows 10我都准备放弃了,太晦涩了,无法理解,还是学学其他的先,动不动就是类,对象,各种概念