关于JS中的constructor与prototype

在学习JS的面向对象过程中,一直对constructor与prototype感到很迷惑,看了一些博客与书籍,觉得自己弄明白了,现在记录如下:

我们都知道,在JS中有一个function的东西。一般人们叫它函数。比如下面的代码:

function Person(name)
{alert(name);
}
Person('js');//js

 




上面的代码中,Person的表现的确跟一般的函数没有什么区别,接着看下面的代码

function Person(name)
{this.name=name;this.showMe=function(){alert(this.name);}
};
var one=new Person('JavaScript');
one.showMe();//JavaScript

 



很多人见到了久违的new操作符,于是就叫Person为“类”,可是又没有关键字class的出现,觉得叫“类”有点勉强。于是退而求其次叫 Person为类的构造函数。这些概念好像都没有错,之所以出现这样的情况,可能是因为大家都学习了传统的面向对象语言(c++,c#,java等),还 有一种思维定势吧。为了让javascript也面向对象,要在javascript中找到与传统面向对象语言的影子。

可是按照javascript的说法,function定义的这个Person就是一个Object(对象),而且还是一个很特 殊的对象,这个使用function定义的对象与使用new操作符生成的对象之间有一个重要的区别。这个区别就是function定义的对象有一个 prototype属性,使用new生成的对象就没有这个prototype属性。

prototype属性又指向了一个prototype对象,注意prototype属性与prototype对象是两个不同的东西,要注意区别。在prototype对象中又有一个constructor属性,这个constructor属性同样指向一个constructor对象,而这个constructor对象恰恰就是这个function函数本身。

有点头晕,看下图吧:



不相信可以看下面的代码:

function Person(name)
{this.name=name;this.showMe=function(){alert(this.name);}
};var one=new Person('js');alert(one.prototype)//undefined
alert(typeof Person.prototype);//object
alert(Person.prototype.constructor);//function Person(name) {...};

 



上面的代码证明了one这个对象没有prototype属性。

我们接着看代码:

function Person(name)
{this.name=name;this.showMe=function(){alert(this.name);}
};Person.prototype.from=function()
{alert('I come from prototype.');
}var one=new Person('js');one.showMe();//js,这个结果没有什么好奇怪的
one.from();//I come from prototype.,这个结果有一点奇怪吧

 



要解释这个结果就要仔细研究一下new这个操作符了.var one=new Person('js');这个语句执行的过程可以分成下面的语句:

var one={};
Person.call(one,'js');

 



按照《悟透javascript》书中说的,new形式创建对象的过程实际上可以分为三步:
第一步是建立一个新对象(叫A吧);

第二步将该对象(A)内置的原型对象设置为构造函数(就是Person)prototype 属性引用的那个原型对象;

第三步就是将该对象(A)作为this 参数调用构造函数(就是Person),完成成员设置等初始化工作。

其中第二步中出现了一个新名词就是内置的原型对象,注意这个新名词跟prototype对象不是一回事,为了区别我叫它inobj,inobj就 指向了函数Person的prototype对象。在person的prototype对象中出现的任何属性或者函数都可以在one对象中直接使用,这个 就是javascript中的原型继承了。

又头晕了,上图吧!



这样one对象通过内置的原型对象inobj就可以直接访问Person的prototype对象中的任何属性与方法了。这也就解释了上面的代码 中为什么one可以访问form函数了。因为prototype对象中有一个constructor属性,那么one也可以直接访问 constructor属性。

function Person(name)
{this.name=name;this.showMe=function(){alert(this.name);}
};Person.prototype.from=function()
{alert('I come from prototype.');
}var one=new Person('js');one.showMe();//js,这个结果没有什么好奇怪的
one.from();//I come from prototype.,这个结果有一点奇怪吧
alert(one.constructor);//function Person(name) {...}
alert(Person.prototype.constructor);//function Person(name) {...}

 



接着看继承是如何实现的。

function Person(name)
{this.name=name;this.showMe=function(){alert(this.name);}
};Person.prototype.from=function()
{alert('I come from prototype.');
}function SubPerson()
{
}
SubPerson.prototype=new Person();var subOne=new SubPerson();
subOne.from();//I come from prototype.
alert(subOne.constructor);//function Person(name) {...};
alert(SubPerson.prototype.constructor);//function Person(name) {...};

 



继承的实现很简单,只需要把子类的prototype设置为父类的一个对象即可。注意这里说的可是对象哦!

那么通过prototype属性实现继承的原理是什么呢?还是先看图形说明,然后编写代码进行验证。



注意:红色的方框就是把子类与父类链接起来的地方。这个就应该是传说中的prototype链了吧。下面有代码进行验证。

function Person(name)
{this.name=name;this.showMe=function(){alert(this.name);}
};Person.prototype.from=function()
{alert('I come from prototype.');
}
var father=new Person('js');//为了下面演示使用showMe方法,采用了js参数,实际多采用无参数
alert(father.constructor);//查看构造函数,结果是:function Person(name) {...};
function SubPer()
{
}
SubPer.prototype=father;//注意这里
SubPer.prototype.constructor=SubPer;var son=new SubPer();
son.showMe();//js
son.from();//I come from prototype.
alert(father.constructor);//function SubPer(){...}
alert(son.constructor);//function SubPer(){...}
alert(SubPer.prototype.constructor);//function SubPer(){...}

 



根据上图的prototype链,还有代码的结果,我想应该明白为什么使用prototype能够实现

JS中的继承了吧。



本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/niuyongjie/archive/2009/11/15/4810835.aspx

转载于:https://www.cnblogs.com/myphoebe/archive/2012/04/10/2440974.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/434582.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java二级缓存技术_Java二级缓存

第一步所需导入架包log4j-api-2.10.0.jarlog4j-core-2.10.0.jarmybatis-3.4.1.jarmysql-connector-java-5.1.38.jar第二步开始配置数据库的连接br> "http://mybatis.org/dtd/mybatis-3-config.dtd">第三步(文件放在src根目录问件下)日志配置第四步&#xff…

resolv.conf

文件/etc/resolv.conf配置DNS客户,它包含了主机的域名搜索顺序和DNS服务器的地址,每一行应包含一个关键字和一个或多个的由空格隔开的参数。下面是一个例子文件: search mydom.edu.cnnameserver 210.34.0.14nameserver 210.34.0.2合法的参数及…

php mvc 路由,PHP手写MVC (五)—— 路由

路由是一个框架中必不可少的组件,其作用是把 URL 按照预定规则解析到特定控制器中。我们在这里定义了两种路由规则:查询字符串。在路径后面使用问号加参数,多个参数用 & 分隔。在配置文件使用 querystring 表示#控制器/方法?参数1值1&am…

ifcfg-eth0 配置

文件:/etc/sysconfig/network-scripts/ifcfg-eth0 以下各值常见于所有的基本配置文件中: * DEVICEname,这里name是物理设备的名字(动态分配的PPP设备应当除外, 它的名字是“逻辑名”。 * IPADDRaddr, 这里addr是IP…

我的收藏 - 音频处理相关网站

自己平时用chrome浏览器,用Google帐号同步标签,但有时还是容易丢失一些网址,因此做个简单的同步!慢慢更新中... 音频相关算法 http://www.jjj.de/fxt/ http://www.dspguide.com/ http://www.musicdsp.org/files/Audio-EQ-Cookb…

php获取跳转前的地址,PHP获取短链接跳转后的真实地址和响应头信息的方法

PHP获取短链接跳转后的真实地址和响应头信息的方法获取到一个短连接,需要将短连接转换成真实的网址,通过查资料,发现 PHP 提供了一个函数 get_headers() ,可以完成这个任务,先把 头部信息获取到,然后再分析…

安装配置opensips过程记录

本文操作系统为CentOS,所用Opensips版本为1.8.2。 Update2013/6/27: 版本1.9.1也已验证通过,下载地址为http://opensips.org/pub/opensips/latest/src/opensips-1.9.1_src.tar.gz 安装CentOS (若已有环境可跳过此步骤) 1、安装虚拟…

eclipse快捷键Alt + /

很多书籍中Eclipse的快捷键Ctrl Space在中文系统中被Alt / 代替转载于:https://www.cnblogs.com/jubincn/archive/2012/04/19/3381206.html

Linux Kbuild文档 1

Linux内核配置方式1.1 概述 Linux内核源代码组织了一个配置系统,该配置系统可以生成内核配置菜单,方便内核配置。配置系统主要包含Makefile、Kconfig和配置工具,可以生成配置界面。其中,配置界面是通过配置工具来生成的&#xff…

依赖注入原理 php,PHP依赖注入原理与用法分析

本文实例讲述了PHP依赖注入原理与用法。分享给大家供大家参考,具体如下:引言依然是来自到喜啦的一道面试题,你知道什么是依赖注入吗?依赖注入(DI)的概念虽然听起来很深奥,但是如果你用过一些新兴的php框架的话&#xf…

jQuery1.7.2正式发布了

下载地址 jQuery1.7.2正式发布了,下载地址: http://code.jquery.com/jquery-1.7.2.min.js (minified, production)http://code.jquery.com/jquery-1.7.2.js (unminified, debug)注:如果你正在使用jQuery Mobile,请使用最新的jQuer…

Linux Kbuild文档 2

2. Kconfig linux在2.6版本以后将配置文件由原来的config.in改为Kconfig,对于Kconfig的语法在内核源代码/Documentation/kbuild/kconfig-language.txt中做了详细的说明。 2.1 Kconfig的树状关系 Kconfig的配置选项是以树的形式组织的,如下所示所示&am…

php upw5.5,UPW

PHP EngineerResponsibilities:●Analysis and module design of software system;●Development and design of new products, and be able to write the core module code independently;●Responsible for the maintenance and upgrading of existing…

cocos2d对动画的各种操作

关于动画的各种操作,总结一下以便以后复习查找。 内容简要: 1、瞬时动作2、延时动作 3、 组合动作 4、动画 5、速度变化6、函数调用7、创建动作动画8、控制动画帧的速度 原文地址: http://blog.csdn.net/dingkun520wy/article/details/7014233 --…

matlab的灰色关联,五种灰色关联度分析matlab代码

《五种灰色关联度分析matlab代码》由会员分享,可在线阅读,更多相关《五种灰色关联度分析matlab代码(3页珍藏版)》请在人人文库网上搜索。1、灰色邓关联分析% p12-the study on the grey relational degree and its applicationFunction R1gld_deng(x)ssi…

Linux Kbuild文档 3

3. Kbuild Makefile Linux内核源代码是通过Makefile组织编译的,Linux2.6内核Makefile的许多特性和2.4内核差别很大,在内核目录的documention/kbuild/makefiles.txt中有详细的说明。 3.1 Makefile的组织结构 Linux内核的Makefile分为5个部分&#xff0…

SQL求解两个时间差

sql 求解两个时间差SELECTDATEDIFF( Second, 2009-8-25 12:15:12, 2009-9-1 7:18:20) --返回相差秒数SELECTDATEDIFF( Minute, 2009-9-1 6:15:12, 2009-9-1 7:18:20) --返回相差分钟数 SELECTDATEDIFF( Day, 2009-8-25 12:15:12,2009-9-1 7:18:20)--返回相差的天数SELEC…

matlab如何画一个平面,matlab 画平面

.framework使用注意、静态库配置及构架合成使用注意: 1.项目中使用的framework中包含了资源文件时,需要手动添加该framework中的资源文件 2.由于动态库(framework默认生成为动态库)不能上架,我们在生成的时候需要修改为 ...spring加载hibernate映射文件的几种方式 &…

Linux Kbuild文档 4

4. 一个使用linux kbuild实现可配置编译的例子 我编写了一个使用Linux kbuild机制实现可配置编译的小例子,工程名为print-example。包括如下如下几个目录: 其中scripts、Makefile、Makefile.flags是从busybox-1.9.0复制过来的。 4.1 运行print 运行m…

php标准输出重定向,python标准输出重定向方式

一. 背景在Python中,文件对象sys.stdin、sys.stdout和sys.stderr分别对应解释器的标准输入、标准输出和标准出错流。在程序启动时,这些对象的初值由sys.__stdin__、sys.__stdout__和sys.__stderr__保存,以便用于收尾(finalization)时恢复标准…