javascript prototype 剖析
学过javascript的一定对prototype不陌生,但是这个究竟是个什么东西,就不一定很清楚。
我们先对prototype进行一个定义:每个函数都有一个prototype属性,这个属性是指向一个对象的引用(通俗点说就是这个prototype属性的值是这个对象的引用),这个对象称为原型对象,原型对象包含函数实例共享的方法和属性,也就是说将函数用作构造函数调用(使用new操作符调用)的时候,新创建的对象会从原型对象上继承属性和方法。
为了更好的理解prototype的设计意图,我们先来说几个概念。
私有的变量和函数:
在函数内定义的变量和函数,如果不对外提供接口,那么外部将无法访问到,也就是变为私有变量和私有函数。
function Obj() {
var a = 0; //私有变量
var fn =function(){ //私有函数
//code
}
}
这样在函数对象Obj外部无法访问变量a和函数fn,它们就变成私有的,只能在Obj内部使用,即使是函数Obj的实例仍然无法访问到这些变量和函数:
代码如下:
var o = new Obj();
console.log(o.a); //undefined
console.log(o.fn); //undefined
静态变量和函数
当定义一个函数后,通过"."为其添加属性和函数,通过函数对象本身可以访问到,但是其实例却访问不到,这样的变量和函数分别被称为静态变量和静态函数。
代码如下:
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
实例变量和函数
在面向对象编程中,我们希望在构造函数定义的时候,能够定义一些属性和方法,实例化后可以访问。
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"字面翻译是"原型",是JavaScript实现继承的主要手段。prototype是JavaScript中函数(function)的一个保留属性,它的值是一个对象(我们称为"prototype对象或原型对象")。
通过函数作为构造函数构造出来的对象都自动拥有构造函数的prototype对象中的成员属性和方法。
其中要点有:
- prototype是函数(function)的一个必备属性(书面一点的说法是"保留属性")(只要是function,就一定有一个prototype属性)
- prototype的值是一个对象
- 可以任意修改函数的prototype属性的值。
- 一个对象会自动拥有这个对象的构造函数的prototype的成员属性和方法
//定义一个函数(构造函数),并定义一些属性和方法用来给另外一个构造函数构造出来的对象继承
var function1=function(){
this.name="function1";
this.saySomething=function(){alert("This's a method of "+this.name);}//定义一个方法
}
//定义另外一个构造函数
var function2=function(){
}
//将构造函数function2的prototype属性设置为一个由function1构造出来的对象,以便使由function2构造出来的对象(并且原本是没有任何属性和方法的对象)拥有function1的属性和方法
function2.prototype=new function1();
var obj1=new function1();
//obj1本来什么成员也没有,多得prototype机制,是它坐享其成地拥有了function1对象的属性和方法。
obj1.saySomething();
那么prototype背后是怎么工作的呢?这里不得不提一个跟prototype一样是系统保留的属性:__proto__
__proto___是一个对象自动拥有的内置属性,指向这个对象的构造函数的prototype对象,才使这个对象认识了它的构造函数的prototype对象,并且拥有了这个prototype对象的属性和方法,比如Person构造函数:

javascript prototype 剖析的更多相关文章
- [原创]javascript prototype 对象 函数 <精简的美丽......>
精简的美丽...... javascript prototype 对象 函数 在javascript中我们都知道创建一个对象使用如下代码var x = {}对象可以拥有属性和方法var x = { ...
- javascript prototype原型链的原理
javascript prototype原型链的原理 说到prototype,就不得不先说下new的过程. 我们先看看这样一段代码: <script type="text/javasc ...
- JavaScript Prototype in Plain Language
非常好的文章: http://javascriptissexy.com/javascript-prototype-in-plain-detailed-language/ jan. 25 2013 14 ...
- JavaScript prototype原型用法
JavaScript对象原型 所有JavaScript对象都从原型继承属性和方法. <!DOCTYPE html> <html> <meta charset=" ...
- illustrating javascript prototype & prototype chain
illustrating javascript prototype & prototype chain 图解 js 原型和原型链 proto & prototype func; // ...
- HTML 学习笔记 JavaScript (prototype)
原博地址:http://www.cnblogs.com/dolphinX/p/3286177.html 原博客的作者是一个非常牛逼的前端大神,我作为一个初学者,在此借助大神的博客进行自己的学习.在这里 ...
- 关于 JavaScript prototype __proto__ 一点总结
http://www.cnblogs.com/wbin91/p/5265163.html 先上代码 function(y) Foo{ this.y = y;} Foo.prototype.x = 10 ...
- JavaScript prototype 使用介绍
用过JavaScript的同学们肯定都对prototype如雷贯耳,但是这究竟是个什么东西却让初学者莫衷一是,只知道函数都会有一个prototype属性,可以为其添加函数供实例访问,其它的就不清楚了, ...
- JavaScript——Prototype详探
用过JavaScript的同学们肯定都对prototype如雷贯耳,但是这究竟是个什么东西却让初学者莫衷一是,只知道函数都会有一个prototype属性,可以为其添加函数供实例访问,其它的就不清楚了, ...
随机推荐
- java 集合(Collection 和 Array)
Collection(是一个单列集合的根接口) Collections(操作集合对象的一个工具类)只要了解部分常用的方法就好
- MySQL和OneSQL并行插入性能对比
按照我的作风,没图说个啥 环境 下面是受叶金荣老师的启发把相关环境交代清楚 MySQL和OneSQL的关键参数配置如下 数据库 sync_binlog innodb_flush_log_at_trx_ ...
- linux笔记:RPM软件包管理-rpm命令管理
rpm包命名原则: rpm包的依赖性: 包名和包全名: rpm软件包安装.升级和卸载: rpm软件包查询: 从rpm包中提取指定文件:
- js时间显示设置
//对日期中部分小于10的数字前边添加0 function zero(s){ return s < 10 ? '0' + s: s; } var date=new Date(), year = ...
- js--题目二
//如何获取下面代码所有元素. <form> <input name="" type="text" /> <input name= ...
- iOS开发数据库SQLite的使用
iOS系统自带Core Data来进行持久化处理,而且Core Data可以使用图形化界面来创建对象,但是Core Data不是关系型数据库,对于Core Data来说比较擅长管理在设备上创建的数据持 ...
- javascript实现对象的继承的方式
在JavaScript将原型链作为实现继承的主要方法.基本原理是利用原型让一个subType引用superType的属性和方法 推荐链接 http://www.jb51.net/article/204 ...
- 使用Yeoman,Grunt和Bower开发AngularJS(译)
使用Yeoman产生AngularJS的主要骨架 使用Grunt加速开发和帮助执行 使用Bower来加入第三方插件和框架——third party plugins/frameworks 一.准备工作 ...
- Maven 系列 二 :Maven 常用命令,手动创建第一个 Maven 项目【转】
1.根据 Maven 的约定,我们在D盘根目录手动创建如下目录及文件结构: 2.打开 pom.xml 文件,添加如下内容: <project xmlns="http://maven.a ...
- Octopus系列之开发过程各个技术点
自定义了页面周期 使用唯一的一个VelocityEngine全局的静态实例,优化了小泥鳅blog中每次请求都要创建VelocityEngine实例对象,减少了对象的开销 通过UA判断请求来自的设备,从 ...