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

对于上面的代码,用浏览器运行后你会发现:

  1. length: 提供的是函数的参数个数
  2. prototype: 是一个object
  3. 其它三个都是function

而对于任何一个函数的声明,它都将会具有上面所述的5个property(方法或者属性).

用过JavaScript的同学们肯定都对prototype如雷贯耳,但是这究竟是个什么东西却让初学者莫衷一是,只知道函数都会有一个prototype属性,可以为其添加函数供实例访问,其它的就不清楚了,最近看了一些 JavaScript高级程序设计,终于揭开了其神秘面纱。

每个函数都有一个prototype属性,这个属性是指向一个对象的引用,这个对象称为原型对象,原型对象包含函数实例共享的方法和属性,也就是说将函数用作构造函数调用(使用new操作符调用)的时候,新创建的对象会从原型对象上继承属性和方法。

私有变量、函数

在具体说prototype前说几个相关的东东,可以更好的理解prototype的设计意图。之前写的一篇JavaScript 命名空间博客提到过JavaScript的函数作用域,在函数内定义的变量和函数如果不对外提供接口,那么外部将无法访问到,也就是变为私有变量和私有函数。

function Obj(){
var a=0; //私有变量
var fn=function(){ //私有函数 }
}

这样在函数对象Obj外部无法访问变量a和函数fn,它们就变成私有的,只能在Obj内部使用,即使是函数Obj的实例仍然无法访问这些变量和函数

var o=new Obj();
console.log(o.a); //undefined
console.log(o.fn); //undefined

静态变量、函数

当定义一个函数后通过 “.”为其添加的属性和函数,通过对象本身仍然可以访问得到,但是其实例却访问不到,这样的变量和函数分别被称为静态变量和静态函数,用过Java、C#的同学很好理解静态的含义。

function Obj(){

            }

            Obj.a=0; //静态变量

            Obj.fn=function(){ //静态函数

            }

            console.log(Obj.a); //0
console.log(typeof Obj.fn); //function var o=new Obj();
console.log(o.a); //undefined
console.log(typeof o.fn); //undefined

实例变量、函数

在面向对象编程中除了一些库函数我们还是希望在对象定义的时候同时定义一些属性和方法,实例化后可以访问,JavaScript也能做到这样

function Obj(){
this.a=[]; //实例变量
this.fn=function(){ //实例方法 }
} console.log(typeof Obj.a); //undefined
console.log(typeof Obj.fn); //undefined var o=new Obj();
console.log(typeof o.a); //object
console.log(typeof o.fn); //function

这样可以达到上述目的,然而

function Obj(){
this.a=[]; //实例变量
this.fn=function(){ //实例方法 }
} var o1=new Obj();
o1.a.push(1);
o1.fn={};
console.log(o1.a); //[1]
console.log(typeof o1.fn); //object
var o2=new Obj();
console.log(o2.a); //[]
console.log(typeof o2.fn); //function

上面的代码运行结果完全符合预期,但同时也说明一个问题,在o1中修改了a和fn,而在o2中没有改变,由于数组和函数都是对象,是引用类型,这就说明o1中的属性和方法与o2中的属性与方法虽然同名但却不是一个引用,而是对Obj对象定义的属性和方法的一个复制。

这个对属性来说没有什么问题,但是对于方法来说问题就很大了,因为方法都是在做完全一样的功能,但是却又两份复制,如果一个函数对象有上千和实例方法,那么它的每个实例都要保持一份上千个方法的复制,这显然是不科学的,这可肿么办呢,prototype应运而生。

prototype

无论什么时候,只要创建了一个新函数,就会根据一组特定的规则为该函数创建一个prototype属性,默认情况下prototype属性会默认获得一个constructor(构造函数)属性,这个属性是一个指向prototype属性所在函数的指针,有些绕了啊,写代码、上图!

function Person(){

            }

根据上图可以看出Person对象会自动获得prototyp属性,而prototype也是一个对象,会自动获得一个constructor属性,该属性正是指向Person对象。

当调用构造函数创建一个实例的时候,实例内部将包含一个内部指针(很多浏览器这个指针名字为__proto__)指向构造函数的prototype,这个连接存在于实例和构造函数的prototype之间,而不是实例与构造函数之间。

function Person(name){
this.name=name;
} Person.prototype.printName=function(){
alert(this.name);
} var person1=new Person('Byron');
var person2=new Person('Frank');

Person的实例person1中包含了name属性,同时自动生成一个__proto__属性,该属性指向Person的prototype,可以访问到prototype内定义的printName方法,大概就是这个样子的

写段程序测试一下看看prototype内属性、方法是能够共享

function Person(name){
this.name=name;
} Person.prototype.share=[]; Person.prototype.printName=function(){
alert(this.name);
} var person1=new Person('Byron');
var person2=new Person('Frank'); person1.share.push(1);
person2.share.push(2);
console.log(person2.share); //[1,2]

果不其然!实际上当代码读取某个对象的某个属性的时候,都会执行一遍搜索,目标是具有给定名字的属性,搜索首先从对象实例开始,如果在实例中找到该属性则返回,如果没有则查找prototype,如果还是没有找到则继续递归prototype的prototype对象,直到找到为止,如果递归到object仍然没有则返回错误。同样道理如果在实例中定义如prototype同名的属性或函数,则会覆盖prototype的属性或函数。

function Person(name){
this.name=name;
} Person.prototype.share=[]; var person=new Person('Byron');
person.share=0; console.log(person.share); //0而不是prototype中的[]

构造简单对象

当然prototype不是专门为解决上面问题而定义的,但是却解决了上面问题。了解了这些知识就可以构建一个科学些的、复用率高的对象,如果希望实例对象的属性或函数则定义到prototype中,如果希望每个实例单独拥有的属性或方法则定义到this中,可以通过构造函数传递实例化参数。

function Person(name){
this.name=name;
} Person.prototype.share=[]; Person.prototype.printName=function(){
alert(this.name);
}
 

javascript prototype学习的更多相关文章

  1. 大量Javascript/JQuery学习教程电子书合集

    [推荐分享]大量Javascript/JQuery学习教程电子书合集,送给有需要的人   不收藏是你的错^_^. 经证实,均可免费下载. 资源名称 资源大小   15天学会jQuery(完整版).pd ...

  2. [推荐分享]大量Javascript/JQuery学习教程电子书合集,送给有需要的人

    不收藏是你的错^_^. 经证实,均可免费下载. 资源名称 资源大小   15天学会jQuery(完整版).pdf 274.79 KB   21天学通JavaScript(第2版)-顾宁燕扫描版.pdf ...

  3. JavaScript 核心学习——继承

    本篇博文讲述如何在 JavaScript 中实现继承,以及原型与原型链的知识,在附录中将会讲述 JavaScript 面向对象的常见错误. ##原型与原型链在 JavaScript 中,使用类将会付出 ...

  4. [原创]javascript prototype 对象 函数 <精简的美丽......>

    精简的美丽...... javascript prototype 对象 函数 在javascript中我们都知道创建一个对象使用如下代码var x = {}对象可以拥有属性和方法var x = {   ...

  5. 正则表达式(javascript)学习总结

    正则表达式在jquery.linux等随处可见,已经无孔不入.因此有必要对这个工具认真的学习一番.本着认真.严谨的态度,这次总结我花了近一个月的时间.但本文无任何创新之处,属一般性学习总结. 一.思考 ...

  6. JavaScript 基础学习1-day14

    JavaScript 基础学习1 知识预览JavaScript概述二 JavaScript的基础三 JavaScript的对象BOM对象DOM对象实例练习js扩展 JavaScript概述 JavaS ...

  7. JavaScript正则表达式学习笔记(二) - 打怪升级

    本文接上篇,基础部分相对薄弱的同学请移步<JavaScript正则表达式学习笔记(一) - 理论基础>.上文介绍了8种JavaScript正则表达式的属性,本文还会追加介绍几种JavaSc ...

  8. 初步总结javascript中学习DOM之前的知识

    嘿嘿,又到了周末时间,周六其实就是总结这周的学习的,记得周二周三刚开始接触javascript时间,还是不知道怎么学习的,就感觉找不到方向,那时间学习的只是总结了一些简单的定义或者是学习结构,今天就把 ...

  9. JavaScript紧凑学习

    JavaScript紧凑学习 windows本地,调用命令行: win键+R 键入cmd , (cmd是Command 命令行 简称) 目录是C盘下的 C:\Users\Administrator&g ...

随机推荐

  1. Objective-c: 移除字符串中的指定字符

    string = [[string componentsSeparatedByCharactersInSet:[NSCharacterSet characterSetWithCharactersInS ...

  2. slab着色,可以减少cache conflict miss概率么?

    以内部slab为例,管理区 + object总大小+left_over size = 1page,我们做个极端假设,cache为 direct-mapped caches. 1.没有采用slab着色: ...

  3. [转]jmeter实战

    [转]http://blog.csdn.net/ultrani/article/details/8309932 本文主要介绍性能测试中的常用工具jmeter的使用方式,以方便开发人员在自测过程中就能自 ...

  4. jenkins 升级jdk到1.8.0 报java.io.IOException:Unable to read /var/lib/jenkins/config.xml

    今天手动下载安装了jdk1.8.0, 并修改了配置文件,当前默认使用该版本的jdk.但是报出一下错误: 问题查到: https://issues.jenkins-ci.org/browse/JENKI ...

  5. qt creator如何实现转到槽功能

    ui_mainwindow.h .

  6. MTK 关闭安全模式

    1.当 Android 设备在安全模式(Safe Mode)下工作时,任何的第三方应用程序或相关文件(主要为apk应用程序文件)都不可以使用,但可以使用 Android 设备的任务管理器选项进行卸载或 ...

  7. 关于Android中Animation的停止【转载】

    转载自:http://blog.csdn.net/easonx1990/article/details/8231520 最近遇到一个需求,通过在GridView上改变焦点,并且GridView上每个i ...

  8. 虚拟机安装linux系统无法上网的解决方法

    原文:https://www.jb51.net/article/118267.htm 周末闲来无事,用虚拟机安装了centos6.5系统,安装成功后发现不能连接网络,然后我就一脸蒙蔽了,无奈之下,只能 ...

  9. Java NIO原理 图文分析及代码实现

    Java NIO原理图文分析及代码实现 前言:  最近在分析hadoop的RPC(Remote Procedure Call Protocol ,远程过程调用协议,它是一种通过网络从远程计算机程序上请 ...

  10. NetBpm如何指定下一流程处理人(8)

    NETBPM如何指定下一流程处理人 本着“软件以应用为本”(潘加宇老师对我的影响在这一点上很深.)的原则,我为ERP搭建了一个用NETBPM作的支持网站,想着能够看着软件得以应用,自是非常高兴. 不过 ...