领悟JavaScript面向对象
JavaScript 是面向对象的。但是不少人对这一点理解得并不全面。
在 JavaScript 中,对象分为两种。一种可以称为“普通对象”,就是我们所普遍理解的那些:数字、日期、用户自定义的对象(如:{})等等。
还有一种,称为“方法对象”,就是我们通常定义的 function。你可能觉得奇怪:方法就是方法,怎么成了对象了?但是在 JavaScript 中,方法的确是被当成对象来处理的。下面是一个简单的例子:
- function func() {alert( 'Hello!' );}
- alert(func.toString());
function func() {alert('Hello!');}
alert(func.toString());
在这个例子中,func 虽然是作为一个方法定义的,但它自身却包含一个 toString 方法,说明 func 在这里是被当成一个对象来处理的。更准确的说,func 是一个“方法对象”。下面是例子的继续:
- func.name = “I am func.”;
- alert(func.name);
func.name = “I am func.”;
alert(func.name);
我们可以任意的为 func 设置属性,这更加证明了 func 就是一个对象。那么方法对象和普通对象的区别在哪里呢?首先方法对象当然是可以执行的,在它后面加上一对括号,就是执行这个方法对象了。
- func();
func();
所以,方法对象具有二重性。一方面它可以被执行,另一方面它完全可以被当成一个普通对象来使用。这意味着什么呢?这意味着方法对象是可以完全独立于其他对象存在的。这一点我们可以同 Java 比较一下。在 Java 中,方法必须在某一个类中定义,而不能单独存在。而 JavaScript 中就不需要。
方法对象独立于其他方法,就意味着它能够被任意的引用和传递。下面是一个例子:
- function invoke(f) {
- f();
- }
- invoke(func);
function invoke(f) {
f();
}
invoke(func);
将一个方法对象 func 传递给另一个方法对象 invoke,让后者在适当的时候执行 func。这就是所谓的“回调”了。另外,方法对象的这种特殊性,也使得 this 关键字不容易把握。这方面相关文章不少,这里不赘述了。
除了可以被执行以外,方法对象还有一个特殊的功用,就是它可以通过 new 关键字来创建普通对象。
话说每一个方法对象被创建时,都会自动的拥有一个叫 prototype 的属性。这个属性并无什么特别之处,它和其他的属性一样可以访问,可以赋值。不过当我们用 new 关键字来创建一个对象的时候,prototype 就起作用了:它的值(也是一个对象)所包含的所有属性,都会被复制到新创建的那个对象上去。下面是一个例子:
- func.prototype.name=”prototype of func”;
- var f = new func();
- alert(f.name);
func.prototype.name=”prototype of func”;
var f = new func();
alert(f.name);
执行的过程中会弹出两个对话框,后一个对话框表示 f 这个新建的对象从 func.prototype 那里拷贝了 name 属性。而前一个对话框则表示 func 被作为方法执行了一遍。你可能会问了,为什么这个时候要还把 func 执行一遍呢?其实这个时候执行 func,就是起“构造函数”的作用。为了形象的说明,我们重新来一遍:
- function func() {
- this.name=”name has been changed.”
- }
- func.prototype.name=”prototype of func”;
- var f = new func();
- alert(f.name);
function func() {
this.name=”name has been changed.”
}
func.prototype.name=”prototype of func”;
var f = new func();
alert(f.name);
你就会发现 f 的 name 属性不再是"prototype of func",而是被替换成了"name has been changed"。这就是 func 这个对象方法所起到的“构造函数”的作用。所以,在 JavaScript 中,用 new 关键字创建对象是执行了下面三个步骤的:
- 创建一个新的普通对象;
- 将方法对象的 prototype 属性的所有属性复制到新的普通对象中去。
- 以新的普通对象作为上下文来执行方法对象。
对于“new func()”这样的语句,可以描述为“从 func 创建一个新对象”。总之,prototype 这个属性的唯一特殊之处,就是在创建新对象的时候了。
那么我们就可以利用这一点。比如有两个方法对象 A 和 B,既然从 A 创建的新对象包含了所有 A.prototype 的属性,那么我将它赋给 B.prototype,那么从 B 创建的新对象不也有同样的属性了?写成代码就是这样:
- A.prototype.hello = function(){alert('Hello!');}
- B.prototype = new A();
- new B().hello();
A.prototype.hello = function(){alert('Hello!');}
B.prototype = new A();
new B().hello();
这就是 JavaScript 的所谓“继承”了,其实质就是属性的拷贝,这里利用了 prototype 来实现。如果不用 prototype,那就用循环了,效果是一样的。所谓“多重继承”,自然就是到处拷贝了。
JavaScript 中面向对象的原理,就是上面这些了。自始至终我都没提到“类”的概念,因为 JavaScript 本来就没有“类”这个东西。面向对象可以没有类吗?当然可以。先有类,然后再有对象,这本来就不合理,因为类本来是从对象中归纳出来的,先有对象再有类,这才合理。像下面这样的:
- var o = {}; // 我发现了一个东西。
- o.eat = function(){return "I am eating."} // 我发现它会吃;
- o.sleep = function(){return "ZZZzzz..."} // 我发现它会睡;
- o.talk = function(){return "Hi!"} // 我发现它会说话;
- o.think = function(){return "Hmmm..."} // 我发现它还会思考。
- var Human = new Function(); // 我决定给它起名叫“人”。
- Human.prototype = o; // 这个东西就代表了所有“人”的概念。
- var h = new Human(); // 当我发现其他同它一样的东西,
- alert(h.talk()) // 我就知道它也是“人”了!
领悟JavaScript面向对象的更多相关文章
- JavaScript学习笔记(三)——this、原型、javascript面向对象
一.this 在JavaScript中this表示:谁调用它,this就是谁. JavaScript是由对象组成的,一切皆为对象,万物皆为对象.this是一个动态的对象,根据调用的对象不同而发生变化, ...
- JavaScript学习总结(三)——this、原型、javascript面向对象
一.this 在JavaScript中this表示:谁调用它,this就是谁. JavaScript是由对象组成的,一切皆为对象,万物皆为对象.this是一个动态的对象,根据调用的对象不同而发生变化, ...
- Javascript面向对象特性实现封装、继承、接口详细案例——进级高手篇
Javascript面向对象特性实现(封装.继承.接口) Javascript作为弱类型语言,和Java.php等服务端脚本语言相比,拥有极强的灵活性.对于小型的web需求,在编写javascript ...
- javascript面向对象系列第四篇——选项卡的实现
前面的话 面向对象的应用并非只是读几本书那么容易,需要有大量的工程实践做基础才能真正理解并学会使用它.本文将用面向对象的技术来制作一个简单的选项卡 图示说明 由图示结果看到,这是一个非常简单的选项卡. ...
- javascript面向对象系列第三篇——实现继承的3种形式
× 目录 [1]原型继承 [2]伪类继承 [3]组合继承 前面的话 学习如何创建对象是理解面向对象编程的第一步,第二步是理解继承.本文是javascript面向对象系列第三篇——实现继承的3种形式 [ ...
- javascript面向对象系列第一篇——构造函数和原型对象
× 目录 [1]构造函数 [2]原型对象 [3]总结 前面的话 一般地,javascript使用构造函数和原型对象来进行面向对象编程,它们的表现与其他面向对象编程语言中的类相似又不同.本文将详细介绍如 ...
- Javascript面向对象(封装、继承)
Javascript 面向对象编程(一):封装 作者:阮一峰 Javascript是一种基于对象(object-based)的语言,你遇到的所有东西几乎都是对象.但是,它又不是一种真正的面向对象编程( ...
- 《javascript面向对象精要》读书笔记
<javascript面向对象精要> 买这本书的原因主要是因为作者,Nicholas C. Zakas 牛X闪闪的js专家,读过js高程的应该都知道他,而这本书是他的最新力作,感觉也是js ...
- 【转】javascript面向对象编程
摘要:本文本来是想自己写的,奈何花了好长时间写好之后忘记保存,还按了刷新键,一键回到解放前,索性不写了,所以本文是转载的. 面向对象编程是用抽象方式创建基于现实世界模型的一种编程模式,主要包括模块化. ...
随机推荐
- php 面试常问 基础知识
字符串都是海针 数组是针海 输出及打印 echo 8%(-2); //输出结果为0 模后的正负号可无视 模前的有用 echo date('Y-m-d H:i:s',strtotime('-1 day' ...
- Asp.Net实现在线人数统计 (转)
原文件:http://blog.csdn.net/wxd_860825/article/details/4589292 利用Application对象和Session对象可以统计当前在线用户数量. 注 ...
- 【BZOJ4566】[HAOI2016]找相同字符
[BZOJ4566][HAOI2016]找相同字符 题面 给定两个字符串,求出在两个字符串中各取出一个子串使得这两个子串相同的方案数.两个方案不同当且仅当这两个子串中有一个位置不同. 其中\(1\le ...
- SRM 563 500pts SpellCards
SpellCards 题意: 有n张符卡排成一个队列,每张符卡有两个属性,等级li和伤害di. 两种操作: 1.把队首的符卡移动到队尾:2.使用队首的符卡,对敌人造成di点伤害,并丢弃队首的li张符卡 ...
- idea 安装后需要手动设置 64位的vmoptions (为了更好的性能和体验)
- sklearn半监督学习
标签: 半监督学习 作者:炼己者 欢迎大家访问 我的简书 以及 我的博客 本博客所有内容以学习.研究和分享为主,如需转载,请联系本人,标明作者和出处,并且是非商业用途,谢谢! --- 摘要:半监督学习 ...
- 函数parseQuery用于解析url查询参数
在百度上找的,以后忘了再看. 语法如下: var obj = parseQuery(query) query是被解析的查询参数,函数返回解析后的对象. 使用范例如下: var jerry = pars ...
- [network]交换机中用户权限
LEVEL 0(访问级):可以执行用于网络诊断等功能的命令.包括ping.tracert.telnet等命令,执行该级别命令的结果不能被保存到配置文件中. LEVEL 1(监控级):可以执行用于系统维 ...
- 洛谷【P1057】传球游戏
https://www.luogu.org/problemnew/show/P1057 题目描述 在体育课上, 老师带着同学们一起做传球游戏. 游戏规则是这样的: n 个同学站成一个圆圈, 其中的一个 ...
- 笔试题:C++打印队列
题目:打印队列 题目介绍:现在用打印机打印队列,已知打印任务有9个优先级(1-9),现在给出一系列任务,求输出打印顺序(任务下标,从0开始). 例: 输入:9,3,5,4,7,1 输出:0,4,2,3 ...