javascript入门:prototype和面向对象的实现
由于工作需要,需要大量使用javascript,于是对其进行了一下学习。
学习任何一个语言,最重要的是掌握其和其他语言不同的关键特性。对javascript来说,我总结就是prototype。就像metatable之于lua的地位,如果理解了prototype,再加上其他语言的使用经验,javascript将很容易掌握。
首先,明确一个概念,javascript中所有东西皆是对象,包括函数。这是后面讨论的基础。
关于prototype,相关的概念有两个:
1 一切函数对象,都有一个默认的属性:prototype。
2 一切对象,都有一个默认的属性:__proto__。
比如我写一个函数:
function Speak()
{
alert("speak!");
}
这个函数将会有一个叫做prototype的属性。
prototype更多的只是一个普通的对象(只有在使用new关键字的时候,它才会显出语法层面的特殊性);而__proto__则有特殊的语法意义:
当访问一个对象的属性,而这个属性不存在的时候,将在这个对象的__proto__中寻找这个属性,如果再找不到,就继续找__proto__的__proto__,直到最顶层(Object)。设置时则在对象上增加这个属性。
这个功能,类似于lua中的metatable中的index,如果metatable的index指定了一个表,那么找不到字段时会从那个表里找。
明白了__proto__的意义之后,再说prototype,事实上prototype就是为了设置__proto__而存在的:当使用new关键字调用函数,将把该函数对象的prototype设置到新实例的__proto__上。
例如:
function Animal(hp)
{
this.hp = hp;
} var a = new Animal(20);
此时,a的__proto__将是Animal的prototype。
prototype预置了一个属性叫constructor,constructor如果不主动修改,默认指向自己(本函数对象)。
因此,如果需要添加类成员,只需要在prototype上面加,prototype作为原型,只有一份,所有new出来的对象都使用它的属性。
function Animal(hp)
{
this.hp = hp;
} Animal.prototype.getHP = function() { return this.hp; } var a = new Animal(20);
此时,a.getHP()将调用到Animal.prototype.getHP。
关于类与实例,到这里就没问题了。可以认为prototype就是类模板,Animal(hp)就是构造函数。当调用new的时候,javascript做了下面的事情:
1 创建一个新的对象(Object)。
2 将该对象的__proto__赋值为new后所调用函数的prototype。
3 将该对象赋值给this参数(隐含在参数表中),调用该函数。
4 函数返回后,将该对象作为new表达式的返回值返回。
由于所有对象共享一个prototype,因此,此时要注意一点:如果要定义的类中有属性引用到可能被修改的对象,如:
function Animal(hp)
{
} Animal.prototype.family = {father:"a", mother:"b" }; var a = new Animal();
var b = new Animal();
此时,如果修改了a的father,b的也一起被修改了。因此,这个family字段必须在Animal构造函数中设置,不能放在prototype中。如果该对象不太可能被修改,如纯粹的数值或字符串,就可以放到prototype中。
如果要实现继承,就要利用__proto__的链条形式往上查找属性的特性。将prototype指定为父类的实例。
function Animal(hp)
{
this.hp = hp;
} Animal.prototype.getHP = function() { return this.hp; } function Person(name)
{
this.name = name;
} Person.prototype = new Animal();
Person.prototype.constructor = Person;
Person.prototype.getName = function() { return this.name; } var personInstance = new Person("Eagle");
此时,当我们访问personInstance.getHP,首先personInstance找不到,到personInstance.__proto__中寻找,即Person.prototype,因为Person.prototype是在Animal实例的基础上修改的,其__proto__是Animal.prototype,因此找到了Animal.prototype中的getHP。
解决了继承的问题,但是依然存在一个问题:如何调用父类的构造函数。上面说的getHP实际上调用会出错,因为Animal函数没有被调用过,因此,this.hp = hp这一句没有执行,其实是没有hp属性的。
此时,我们需要在构造函数中嵌套调用父类构造函数,如下:
function Animal(hp)
{
this.hp = hp;
} function Person(name, hp)
{
Animal.call(this, hp); //注意这句话:函数对象的call方法可以显式的修改this指针。如果直接调用Animal(hp),this指向的是global。
this.name = name;
} var a = new Person("Eagle", 100);
到此为止,通过prototype的一套体系,实现了javascript的类,实例和继承。
javascript入门:prototype和面向对象的实现的更多相关文章
- JavaScript入门经典(第7版)读书笔记
断断续续看了十来天,终于看完了,还是学到些东西,这本书还是不错的,各方面都有涉及. 补充了下之前不完善的JS 知识 笔记一般只记必要的东西. Table of Contents 1. JavaScr ...
- 悟透JavaScript(理解JS面向对象的好文章)
引子 编程世界里只存在两种基本元素,一个是数据,一个是代码.编程世界就是在数据和代码千丝万缕的纠缠中呈现出无限的生机和活力. 数据天生就是文静的,总想保持自己固有的本色:而代码却天生活泼,总想改变这个 ...
- JavaScript入门基础
JavaScript基本语法 1.运算符 运算符就是完成操作的一系列符号,它有七类: 赋值运算符(=,+=,-=,*=,/=,%=,<<=,>>=,|=,&=).算术运 ...
- JavaScript入门介绍(一)
JavaScript入门介绍 [经常使用的调试工具][w3school.com.cn在线编辑] [Chrome浏览器 开发调试工具]按F121.代码后台输出调试:console.log("t ...
- 开心菜鸟系列----函数作用域(javascript入门篇)
1 <!DOCTYPE html> 2 <html> 3 <script src="./jquery-1.7.2.js"></ ...
- JavaScript - 基于原型的面向对象
JavaScript - 基于原型的面向对象 1. 引言 JavaScript 是一种基于原型的面向对象语言,而不是基于类的!!! 基于类的面向对象语言,比如 Java,是构建在两个不同实体的概念之上 ...
- 第五章 JavaScript对象及初识面向对象
第五章 JavaScript对象及初识面向对象 一.对象 在JavaScript中,所有事物都是对象,如字符串.数值.数组.函数等. 在JavaScript对象分为内置对象和自定义对象,要处理一些 ...
- JAVAScript对象及初始面向对象
javaScript对象及初始面向对象 1:内置对象 例:Date String Array 类等... 2:自定义对象 方法1:var newObj=new Object(); ...
- JavaScript游戏中的面向对象的设计
简介: 从程序角度考虑,许多 JavaScript 都基于循环和大量的 if/else 语句.在本文中,我们可了解一种更聪明的做法 — 在 JavaScript 游戏中使用面向对象来设计.本文将概述原 ...
- Javascript中prototype属性详解 (存)
Javascript中prototype属性详解 在典型的面向对象的语言中,如java,都存在类(class)的概念,类就是对象的模板,对象就是类的实例.但是在Javascript语言体系中,是不 ...
随机推荐
- OpenVpn简单架设
首先Wget wget http://swupdate.openvpn.org/as/openvpn-as-2.0.24-CentOS6.i386.rpm wget http://swupdate.o ...
- delphi XE4 隐藏程序在任务管理器和隐藏任务栏
最新处理方法,偶然发现delphi下有个ShowMainForm属性,只要在Application.Initialize;后面加上Application.ShowMainForm := false;就 ...
- js函数中this的不同含义
1.js函数调用过程中,js线程会进入新的执行环境并创建该环境的变量对象,并添加两个变量:this和arguments,因此可以在函数中使用这两个变量.需要注意的是,this变量不能重新赋值,而arg ...
- DNS解析过程和域名收敛、域名发散、SPDY应用
前段时间项目要做域名收敛,糊里糊涂的完成了,好多原理不清晰,现在整理搜集下知识点. 域名收敛的目的是什么?简单来说就是域名解析慢.那为什么解析慢?且听下文慢慢道来. 什么是DNS? DNS( Doma ...
- poj 1270(toposort)
http://poj.org/problem?id=1270 题意:给一个字符串,然后再给你一些规则,要你把所有的情况都按照字典序进行输出. 思路:很明显这肯定要用到拓扑排序,当然看到discuss里 ...
- Python之反射,正则
本节主要内容: 一. 反射: getattr hasattr setattr defattr 二. 补充模块中特殊的变量 三. 正则表达式 re模块 (一)反射: hasattr(object, na ...
- 数据库Blob数据类型转String
blob数据是存储大对象数据类型, 一般存放二进制的,所以才用字节存取. 首先判断blob数据是否为空,然后采用输入流读出数据,具体代码如下: String content = null; try { ...
- SpringMVC基本配置
1 springmvc 框架 1.1 回顾mvc结构 1.2springmvc的介绍 是一个基于mvc的web层框架,使用spring的一个子项目 在使用springmvc的时候,不用单独和spri ...
- [Android Pro] PullToRefreshListView怎么设置各个item之间的间距
reference to : http://blog.csdn.net/qq_25943493/article/details/50923895 要设置第三方的上拉下载listView的item之间 ...
- 自定义RatingBar,不同分辨率屏幕下图片拉伸或者显示不完整问题解决
1.需要两张评分图片ic_rating_highlight.png ic_rating_normal_white.png(宽高都是52px,且有内边距) 将这两张图片添加到各分辨率文件夹下 开发过 ...