由于工作需要,需要大量使用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和面向对象的实现的更多相关文章

  1. JavaScript入门经典(第7版)读书笔记

    断断续续看了十来天,终于看完了,还是学到些东西,这本书还是不错的,各方面都有涉及. 补充了下之前不完善的JS 知识 笔记一般只记必要的东西.‎ Table of Contents 1. JavaScr ...

  2. 悟透JavaScript(理解JS面向对象的好文章)

    引子 编程世界里只存在两种基本元素,一个是数据,一个是代码.编程世界就是在数据和代码千丝万缕的纠缠中呈现出无限的生机和活力. 数据天生就是文静的,总想保持自己固有的本色:而代码却天生活泼,总想改变这个 ...

  3. JavaScript入门基础

    JavaScript基本语法 1.运算符 运算符就是完成操作的一系列符号,它有七类: 赋值运算符(=,+=,-=,*=,/=,%=,<<=,>>=,|=,&=).算术运 ...

  4. JavaScript入门介绍(一)

    JavaScript入门介绍 [经常使用的调试工具][w3school.com.cn在线编辑] [Chrome浏览器 开发调试工具]按F121.代码后台输出调试:console.log("t ...

  5. 开心菜鸟系列----函数作用域(javascript入门篇)

      1 <!DOCTYPE html>   2 <html>   3 <script src="./jquery-1.7.2.js"></ ...

  6. JavaScript - 基于原型的面向对象

    JavaScript - 基于原型的面向对象 1. 引言 JavaScript 是一种基于原型的面向对象语言,而不是基于类的!!! 基于类的面向对象语言,比如 Java,是构建在两个不同实体的概念之上 ...

  7. 第五章 JavaScript对象及初识面向对象

    第五章   JavaScript对象及初识面向对象 一.对象 在JavaScript中,所有事物都是对象,如字符串.数值.数组.函数等. 在JavaScript对象分为内置对象和自定义对象,要处理一些 ...

  8. JAVAScript对象及初始面向对象

              javaScript对象及初始面向对象 1:内置对象 例:Date String Array 类等... 2:自定义对象 方法1:var newObj=new Object(); ...

  9. JavaScript游戏中的面向对象的设计

    简介: 从程序角度考虑,许多 JavaScript 都基于循环和大量的 if/else 语句.在本文中,我们可了解一种更聪明的做法 — 在 JavaScript 游戏中使用面向对象来设计.本文将概述原 ...

  10. Javascript中prototype属性详解 (存)

    Javascript中prototype属性详解   在典型的面向对象的语言中,如java,都存在类(class)的概念,类就是对象的模板,对象就是类的实例.但是在Javascript语言体系中,是不 ...

随机推荐

  1. debug [LTS]

    0613 A. 复制代码的时候忘了后续的对称的修改. 统计答案时出现了一些不可理喻的低级失误. B. 在0-indexed的程序中访问第一个元素使用了Arr[1]. Matrix-tree为mat[d ...

  2. haproxy测试

    环境: Clients:N台linux, 使用“ab -k -c 20000...” 并发2w 请求haproxy Haproxy Server: R610 2*8核 2.4G Real Server ...

  3. vux 中popup 组件 Mask 遮罩在最上层问题的解决

    1. 问题描述:popup弹出层在遮罩层下面的 2.原因:因为滚动元素和mask遮罩层在同一级,vux框架默认把遮罩层放在body标签下的 3.解决方法:更改一下源码,把mask遮罩层放在popup同 ...

  4. javax.validation.ConstraintViolationException---Hibernate后台实体校验

    javax.validation.ConstraintViolationException ... 71 moreCaused by: javax.validation.ConstraintViola ...

  5. SQL Server 临时禁用和启用所有外键约束(高版本向低版本迁移数据)

    --获得禁用所有外键约束的语句 select 'ALTER TABLE [' + b.name + '] NOCHECK CONSTRAINT ' + a.name +';' as 禁用约束 from ...

  6. LeetCode之104. Maximum Depth of Binary Tree

    -------------------------------- 递归遍历即可 AC代码: /** * Definition for a binary tree node. * public clas ...

  7. <s:property value=""/> 怎么截取返回值的固定长度的字符串

    ------背景-------------------- 列表中某一个字段的内容较长,显示不美观的情况下可以选择使用xxxxx....来显示,具体内容可见详情. ------解决方案--------- ...

  8. 一个请求在Struts2框架中的处理流程

    1.客户端向Servlet容器发起一个请求,将请求封装为HttpServletRequest对象. 2.HttpServletRequest首先经过web.xml中配置的struts2的过滤器,以及s ...

  9. <转>[WinForm] VS2010发布、打包安装程序(超全超详细)

    1. 在vs2010 选择“新建项目”→“ 其他项目类型”→“ Visual Studio Installer→“安装项目”: 命名为:Setup1 . 这是在VS2010中将有三个文件夹, 1.“应 ...

  10. 【转】hibernate缓存:一级缓存和二级缓存

    什么是缓存? 缓存是介于物理数据源与应用程序之间,是对数据库中的数据复制一份临时放在内存中的容器,其作用是为了减少应用程序对物理数据源访问的次数,从而提高了应用程序的运行性能.Hibernate在进行 ...