prototype 原型

javascript 是一种 prototype based programming 的语言, 而与我们通常的 class based programming 有很大 的区别,我列举重要的几点如下:

1. 函数是first class object, 也就是说函数与对象具有相同的语言地位

2. 没有类,只有对象

3. 函数也是一种对象,所谓的函数对象

4. 对象是按 引用 来传递的

那么这种 prototype based programming 的语言如何实现继承呢(OO的一大基本要素), 这也便是 prototype 的由来。

脚本示例:

function foo(a,  b,  c) {
return a * b * c;
}
console.log(foo.length);
console.log(typeof foo.constructor);
console.log(typeof foo.call);
console.log(typeof foo.apply);
console.log(typeof foo.prototype);

运行结果:

对于上面的代码,用浏览器运行后你会发现:
   1. length: 提供的是函数的参数个数
   2. prototype: 是一个object
   3. 其它三个都是function
   而对于任何一个函数的声明,它都将会具有上面所述的5个property(方法或者属性)。

下面我们主要看下prototype:

function  Person(name,  gender) {
this.name  =  name;
this.gender  =  gender;
this.whoAreYou  =   function() { //这个也是所谓的closure, 内部函数可以访问外部函数的变量
var  res  =  "I'm "  +  this.name  +  " and I'm a "  +  this.gender  + ".";
return  res;
};
}
// 那么在由Person创建的对象便具有了下面的几个属性
Person.prototype.age  =  24;
Person.prototype.getAge  =   function() {
return  this.age;
};
flag  =  true;
if (flag) {
var  fun  = new Person("Tower", "male");
console.log(fun.name);
console.log(fun.gender);
console.log(fun.whoAreYou());
console.log(fun.getAge());
}
Person.prototype.salary  =  10000;
Person.prototype.getSalary  =   function() {
return  this.name + "can earn about " + this.salary  + "RMB each month.";
};
// 下面就是最神奇的地方, 我们改变了Person的prototype,而这个改变是在创建fun之后
// 而这个改变使得fun也具有了相同的属性和方法
// 继承的意味即此
if (flag) {
console.log(fun.getSalary());
console.log(fun.constructor.prototype.age);  //而这个相当于你直接调用 Person.prototype.age
console.log(Person.prototype.age);
}

运行结果:

从上面的示例中我们可以发现:

对于prototype的方法或者属性,我们可以动态地 增加, 而由其创建的对象自动会 继承 相关的方法和属性。
另外,每个对象都有一个constructor属性,用于指向创建其的函数对象,如上例中的 fun.constructor 指向的 就是 Person。

那么一个疑问就自然产生了, 函数对象中自身声明的方法和属性与prototype声明的对象有什么差别?
 1. 自身声明的方法和属性是 静态的, 也就是说你在声明后,试图再去增加新的方法或者修改已有的方法,并不会 对由其创建的对象产生影响, 也即继承失败。
 2. 而prototype可以动态地增加新的方法或者修改已有的方法, 从而是 动态的 ,一旦 父函数对象 声明了相关 的prototype属性,由其创建的对象会 自动继承 这些prototype的属性。

继续上面的例子:

    flag  =  true;
// 函数内部声明的方法是静态的,无法传递的
Person.school  =  "ISCAS";
Person.whoAreYou  =   function() {
return  "zhutao";
};  //动态更改声明期的方法,并不会影响由其创建的对象的方法, 即所谓的静态
if (flag) {
console.log(Person.school);
console.log(fun.school);  //输出的是 "undefined"
console.log(Person.whoAreYou());  //输出 zhutao
console.log(fun.whoAreYou());  // I'm Tower and I'm a male.
}
Person.prototype.getSalary  =   function() {
return  "I can earn 1000000 USD";
};
if (flag) {
console.log(fun.getSalary());  //已经继承了改变, 即所谓的 动态
}

运行结果:

既然有函数对象本身的属性, 也有prototype的属性, 那么是由其创建的对象是如何搜索相应的属性的呢?

基本是按照下面的流程和顺序来进行:

1. 先去搜索函数对象本身的属性,如果找到立即执行。
      2. 如果1没有找到,则会去搜索prototype属性,有2种结果,找到则直接执行,否则继续搜索父对象的父对象的prototype, 直至找到,或者到达 prototype chain 的结尾(结尾会是Object对象)。

以上也说明,如果函数对象本身的属性与prototype属性相同(重名)时的解决方式, 函数本身的对象优先。

再看一个多重prototype链的例子:

function  Employee(name) {
this.name  =  "";
this.dept  =  "general";
this.gender  =  "unknown";
} function  WorkerBee() {
this.projects  =   [];
this.hasCar  =  false;
}
WorkerBee.prototype  =  new  Employee;  // 第一层prototype链
function  Engineer() {
this.dept  =  "engineer";  //覆盖了 "父对象"
this.language  =  "javascript";
}
Engineer.prototype  =  new  WorkerBee;  // 第二层prototype链
var  jay  =  new  Engineer("Jay");
if (flag) {
console.log(jay.dept);  //engineer, 找到的是自己的属性
console.log(jay.hasCar);  // false, 搜索到的是自己上一层的属性
console.log(jay.gender);  // unknown, 搜索到的是自己上二层的属性
}

运行结果:

总结:

1、javascript的prototype给语言本身增加了很强的灵活性,但与class based programming相比整个思维逻辑还是有很大的不同,所以需要更多地思考和揣摩。

2、而javascript是披着c语言外衣的函数式语言,理解自然也需要更多地思考。

javascript 之 prototype 浅析的更多相关文章

  1. javascript订阅模式浅析和基础实例

    前言 最近在开发redux或者vux的时候,状态管理当中的createStore,以及我们在组件中调用的dispatch传递消息给状态管理中心,去处理一些操作的时候,有些类似我们常见到订阅模式 于是写 ...

  2. Javascript: 从prototype漫谈到继承(2)

    本文同时也发表在我另一篇独立博客 <Javascript: 从prototype漫谈到继承(2)>(管理员请注意!这两个都是我自己的原创博客!不要踢出首页!不是转载!已经误会三次了!) 上 ...

  3. JavaScript 笔记 ( Prototype )

    这阵子实在好忙 ( 这样说好像也不是一两个月了... ),然后因为工作伙伴都是 JavaScript 神之等级的工程师,从中也学到不少知识,毕竟就是要和强者工作才会成长呀!为了想好好瞭解他们写的程式码 ...

  4. Javascript Array.prototype.some()

    当我们使用数组时,查找数组中包含某个特殊的项是非常常见的动作.下面例子是一个简单的实现: 01 planets = [ 02     "mercury", 03     " ...

  5. JavaScript和prototype

    Protoype这个词在javascript中可以有两种理解: 第一种是作为javascript中的一个属性,其一般出现的形式为:类名.prototype. prototype 属性让你有能力向对象添 ...

  6. 在 JavaScript 中 prototype 和 __proto__ 有什么区别

    本文主要讲三个 问题 prototype 和 proto function 和 object new 到底发生了什么 prototype 和 proto 首先我们说下在 JS 中,常常让我们感到困惑的 ...

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

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

  8. javascript继承—prototype最优两种继承(空函数和循环拷贝)

    一.利用空函数实现继承 参考了文章javascript继承-prototype属性介绍(2) 中叶小钗的评论,对这篇文章中的方案二利用一个空函数进行修改,可以解决创建子类对象时,父类实例化的过程中特权 ...

  9. (转载)详解Javascript中prototype属性(推荐)

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

随机推荐

  1. 基于spring和Quartz定时器

    最近做一个小项目,要每7天去调用webservice获取一次数据.所以就用定时器来完成spring是4.1.6,quartz是2.2.1. 首先配置spring的xml文件.首先定义你要被执行的类 & ...

  2. Linq解析带命名空间、前缀、Soap格式的XML

    关于XML,经常会用到,XML有一般的,同样也有二般的,更不要觉得会操作基础的XML就觉得自己已经精通XML操作,文中是对解析XML的方法进行介绍 1. 一般XML <?xml version= ...

  3. catalina

    用catalina启动tomcat容器,将项目放到tomcat中,通过cmd:启动:catalina,相当于本地的测试环境.

  4. 压力测试工具JMeter入门教程

    1.Jmeter 概要描叙 jmeter 是一款专门用于功能测试和压力测试的轻量级测试开发平台.多数情况下是用作压力测试,该测试工具在阿里巴巴有着广泛的使用,估计是不要钱吧,哈哈,功能上来说,整个平台 ...

  5. js-sort数组排序

    婆婆妈妈,直上代码: <body> <div> sort()对数组排序,不开辟新的内存,对原有数组元素进行调换 </div> <div id="sh ...

  6. easyui关于validatebox实现多重规则验证的实践

    参考资料 http://blog.csdn.net/jumtre/article/details/38510975 http://blog.csdn.net/lybwwp/article/detail ...

  7. GreenDao关系建表

    关系 在greenDAO,实体涉及使用一对一或一对多的关系.例如,如果要模拟一个1:greenDAOñ关系,你将有一个一对一和一对多的关系.但是,请注意,一对一和一对多的关系不是相互连接,所以你必须同 ...

  8. SeleniumIDE从0到1 (Selenium IDE 回放)

    录制完脚本后可以对录制的脚本进行回放操作. 简介一: 调回放进度(快/慢),点击按钮即可自动进行回放操作.

  9. Cardboard开发教程:使用Unity制作Cardboard全景图片浏览器

    这两年,虚拟现实(VR)领域很火,很多人认为这将会是下一个手机般改变人们生活的技术.目前全球最领先的还是Facebook旗下的Oculus,HTC VIVE,以及最流行的Cardboard.国内多家厂 ...

  10. RabbitMQ 入门 Helloworld

    1.介绍 RabbitMQ 是信息传输的中间者.本质上,他从生产者(producers)接收消息,转发这些消息给消费者(consumers).换句话说,他能够按根据你指定的规则进行消息转发.缓冲.和持 ...