深入理解JavaScript的对象模型
来源:互联网 发布:淘宝评价怎么看不到 编辑:程序博客网 时间:2024/06/05 08:39
1 重要陈述
JavaScript 是面向对象语言
它以自己独特的方式实现了面向对象语言中的封装,抽象,继承,多态等特性;
JavaScript 没有类的概念,只有对象;
现实世界也是面向对象的,也没有类,到处都是“人”的实例,但并没有“人类”这个实体;工厂里生产各式各样的汽车,汽车是实例,并没有所谓的“汽车类”;类,从本质上讲是“知识”。
编程的本质
程序的本质是信息处理(存储,传输,转换,检索,呈现…)。汇编语言,基于“数据”和“指令”编程;面向过程语言(c语言),是基于“变量”和“函数”编程;面向对象语言以“面向对象”的思想去思考和处理“数据”和“行为”,基于对象编程。
数据和行为
从编程的角度看,数据就是特定的内存空间(栈/堆),行为是可执行的代码指令。
2 对象
JavaScript的对象可以直接对数据和函数进行封装:
var s = { name: "s", say: function() { console.log("Hello!") }}s.names.say()
从面向对象的角度来看,同一类型的不同对象之间的公共行为是一样,也就是他们能够共享对象方法。在Java中,所有的对象方法都定义在类信息里,对象实例只包含数据成员。
那么JavaScript是如何把行为抽象出来的呢?
2.1 函数
函数是对可执行语句的封装。在JavaScript中,函数也是对象。
以Java为例,抽象本质上就做了两件事——确定对象空间的大小和关联对象方法。Java通过类定义来实现抽象,可是JavaScript并没有类的概念,于是JavaScript只能通过函数来实现对象的抽象。
function Person(name){ this.name=name; this.say = function(){ console.log("I'm "+this.name) }}var p = new Person("da bao")
- 当调用 new 操作符时,解释器会创建一个通用对象(Object),将其作为this传递给构造函数,也就是该例子中的 A()。
- 构造函数中对 this 的属性进行赋值;
- 然后隐式地(由解释器完成,不需要额外的代码)将内部的prototype属性设置为构造函数A的prototype值。
- 返回新创建的对象。
在JavaScript中,任何函数都可以作为构造函数!如上例,该构造函数很好的完成了封装,指定了对象p的大小{name,say},也实现了创建对象过程的复用。
但是该方式也存在问题:每个对象的存储空间都包含了独立的函数对象 s。如果对象有50个方法呢?将造成极大的空间浪费,Java类的对象可不是这样的哦!
另外一个问题是如何实现类变量(静态变量),也就是所有对象都共享的成员变量,在Java中通过 static 实现!
这就到了 prototype 大显身手的时候了!JavaScript 为每个函数设计了一个 prototype 属性,
2.2 抽象——方法与静态变量
prototype
每个函数都有一个prototype属性,是一个指针,指向该函数的原型对象。
__proto__
是一个对象拥有的内置属性。在JS内部使用寻找原型链。
function Person(name){ this.name=name; Person.prototype.count++;}Person.prototype.say = function(){ console.log("I'm "+this.name)}Person.prototyp.count = 0var p1 = new Person("da bao")var p2 = new Person("er bao")p1.say() // I'm da baop2.say() // I'm er baop1.count // 2p2.count // 2
- 构造函数 prototype 中的属性值,对所有对象来说是共享的,类似于Java中的静态成员。
- 在构造函数中通过 this 赋值的变量,以及调用父类构造函数通过 this 赋值的变量,都是对象独享的。
2.3 继承
面向对象的另一大特性——继承,Java 通过 extends和implements,标识类之间的继承关系,编译器会根据标识隐式的进行对象存储空间的分配和类信息的关联。
JavaScript 是如何实现的呢?
function Worker(name, type){ Person.call(this, name); // (1) this.type = type; Worker.prototype.num++;}Worker.prototype = Object.create(Person.prototype) // (2)Worker.prototype.num = 0var w1 = new Worker("da bao", "Teacher")var w2 = new Worker("er bao", "Coder")w1.say() // I'm da baow2.say() // I'm er baow1.__proto__ == Worker.prototype // TrueWorker.prototype.__proto__ == Person.prototype // True
例子中,(1)处代码保证为父类数据成员分配内存空间并初始化。(2)处代码保证对象能够调用父类中的成员方法。
JavaScript 是基于原型的面向对象语言,每一个js 对象都有一个原型链,这个原型链是一个原型对象之链;当修改构造函数的原型对象时,并不会影响已经存在的对象的原型链。
特别注意:
prototype 是个指针,当对它重新赋值时,已经生成的对象的原型链并不会被改变。
本例的原型链:
Person.prototype.__proto__ == Object.prototypeWorker.prototype.__proto__ == Person.prototypew1.__proto__ == Work.prototype
- 构造函数是对初始化代码的封装;并调用父类的构造函数;
- 原型链是由解释器隐式维护的;就像C++中的虚表,Java对象的头信息;
- 对象的数据成员是由构造函数极其父类构造函数一同决定的,与原型无关;
……
- 深入理解JavaScript的对象模型
- javascript 对象的深入理解
- 深入理解C#的对象模型
- 深入理解JavaScript的原型对象
- 深入理解JavaScript的原型对象
- 深入理解Javascript window对象
- 深入理解Javascript window对象
- 深入理解Javascript window对象
- 深入理解Javascript window对象
- 深入理解JavaScript----- 一切都是对象
- JavaScript深入理解之对象
- 深入理解javascript的4种对象创建方式
- 深入理解javascript(2):函数和对象的关系
- 【六】深入理解javascript创建对象的七种方式
- javascript学习记录(三)-this对象的深入理解
- 深入理解 JavaScript 对象的特性与最佳实践
- 学习《深入理解C++对象模型》小结
- 学习《深入理解C++对象模型》小结
- java开发必看|Spring基础知识汇总
- 挂钩可用于各种构建步骤、
- TCP三次握手四次挥手详解
- tomcat配置本地开发虚拟域名
- 自动化engine-setup
- 深入理解JavaScript的对象模型
- 插入排序及优化(java实现)
- CVE-2011-0104浅析-excel栈溢出漏洞
- MySQL中InnoDB的间隙锁问题
- 【数据结构】链表的原理及java实现
- Linux 下获取Root权限的几种方法
- 神舟笔记本如何进BIOS设置u盘启动?
- 分享SourceTree的分支创建切换合并删除和标签管理等操作
- HTML,css旋转轮播图