谈谈js中的prototype及prototype属性解释和常用方法


Posted in Javascript onNovember 25, 2015

prototype是javascript中笔记难理解的一部分内容,下面通过几个关键知识点给大家讲解js中的prototype。具体内容请看下文详情。

1 原型法设计模式

在.Net中可以使用clone()来实现原型法

原型法的主要思想是,现在有1个类A,我想要创建一个类B,这个类是以A为原型的,并且能进行扩展。我们称B的原型为A。

2 javascript的方法可以分为三类:

a 类方法
b 对象方法
c 原型方法

例子:

function People(name)
{
 this.name=name;
 //对象方法
 this.Introduce=function(){
 alert("My name is "+this.name);
 }
}
//类方法
People.Run=function(){
 alert("I can run");
}
//原型方法
People.prototype.IntroduceChinese=function(){
 alert("我的名字是"+this.name);
}
//测试
var p1=new People("Windking");
p1.Introduce();
People.Run();
p1.IntroduceChinese();

3 obj1.func.call(obj)方法

意思是将obj看成obj1,调用func方法

好了,下面一个一个问题解决:

prototype是什么含义?

javascript中的每个对象都有prototype属性,Javascript中对象的prototype属性的解释是:返回对象类型原型的引用。

A.prototype = new B();

理解prototype不应把它和继承混淆。A的prototype为B的一个实例,可以理解A将B中的方法和属性全部克隆了一遍。A能使用B的方法和属性。这里强调的是克隆而不是继承。可以出现这种情况:A的prototype是B的实例,同时B的prototype也是A的实例。

先看一个实验的例子:

function baseClass()
{
 this.showMsg = function()
 {
  alert("baseClass::showMsg"); 
 }
}
function extendClass()
{
}
extendClass.prototype = new baseClass();
var instance = new extendClass();
instance.showMsg(); // 显示baseClass::showMsg

我们首先定义了baseClass类,然后我们要定义extentClass,但是我们打算以baseClass的一个实例为原型,来克隆的extendClass也同时包含showMsg这个对象方法。

extendClass.prototype = new baseClass()就可以阅读为:extendClass是以baseClass的一个实例为原型克隆创建的。

那么就会有一个问题,如果extendClass中本身包含有一个与baseClass的方法同名的方法会怎么样?

下面是扩展实验2:

function baseClass()
{
 this.showMsg = function()
 {
  alert("baseClass::showMsg"); 
 }
}
function extendClass()
{
 this.showMsg =function ()
 {
  alert("extendClass::showMsg");
 }
}
extendClass.prototype = new baseClass();
var instance = new extendClass();
instance.showMsg();//显示extendClass::showMsg

实验证明:函数运行时会先去本体的函数中去找,如果找到则运行,找不到则去prototype中寻找函数。或者可以理解为prototype不会克隆同名函数。

那么又会有一个新的问题:

如果我想使用extendClass的一个实例instance调用baseClass的对象方法showMsg怎么办?

答案是可以使用call:

extendClass.prototype = new baseClass();
var instance = new extendClass();
var baseinstance = new baseClass();
baseinstance.showMsg.call(instance);//显示baseClass::showMsg

这里的baseinstance.showMsg.call(instance);阅读为“将instance当做baseinstance来调用,调用它的对象方法showMsg”

好了,这里可能有人会问,为什么不用baseClass.showMsg.call(instance);

这就是对象方法和类方法的区别,我们想调用的是baseClass的对象方法

最后,下面这个代码如果理解清晰,那么这篇文章说的就已经理解了:

<script type="text/javascript">
function baseClass()
{
 this.showMsg = function()
 {
  alert("baseClass::showMsg"); 
 }
 this.baseShowMsg = function()
 {
  alert("baseClass::baseShowMsg");
 }
}
baseClass.showMsg = function()
{
 alert("baseClass::showMsg static");
}
function extendClass()
{
 this.showMsg =function ()
 {
  alert("extendClass::showMsg");
 }
}
extendClass.showMsg = function()
{
 alert("extendClass::showMsg static")
}
extendClass.prototype = new baseClass();
var instance = new extendClass();
instance.showMsg(); //显示extendClass::showMsg
instance.baseShowMsg(); //显示baseClass::baseShowMsg
instance.showMsg(); //显示extendClass::showMsg
baseClass.showMsg.call(instance);//显示baseClass::showMsg static
var baseinstance = new baseClass();
baseinstance.showMsg.call(instance);//显示baseClass::showMsg
</script>

ps:js的Prototype属性 解释及常用方法

函数:原型

每一个构造函数都有一个属性叫做原型(prototype,下面都不再翻译,使用其原文)。这个属性非常有用:为一个特定类声明通用的变量或者函数。

prototype的定义

你不需要显式地声明一个prototype属性,因为在每一个构造函数中都有它的存在。你可以看看下面的例子:

Example PT1
CODE:

function Test()
{
}
alert(Test.prototype); // 输出 "Object"

给prototype添加属性

就如你在上面所看到的,prototype是一个对象,因此,你能够给它添加属性。你添加给prototype的属性将会成为使用这个构造函数创建的对象的通用属性。
例如,我下面有一个数据类型Fish,我想让所有的鱼都有这些属性:livesIn="water"和price=20;为了实现这个,我可以给构造函数Fish的prototype添加那些属性。

Example PT2

CODE:

function Fish(name, color)
{
this.name=name;
this.color=color;
}
Fish.prototype.livesIn="water";
Fish.prototype.price=20;

接下来让我们作几条鱼:

CODE:

var fish1=new Fish("mackarel", "gray");
var fish2=new Fish("goldfish", "orange");
var fish3=new Fish("salmon", "white");

再来看看鱼都有哪些属性:

CODE:

for (int i=1; i<=3; i++)
{
var fish=eval_r("fish"+i); // 我只是取得指向这条鱼的指针
alert(fish.name+","+fish.color+","+fish.livesIn+","+fish.price);
}

输出应该是:

CODE:

"mackarel, gray, water, 20"
"goldfish, orange, water, 20"
"salmon, white water, 20"

你看到所有的鱼都有属性livesIn和price,我们甚至都没有为每一条不同的鱼特别声明这些属性。这时因为当一个对象被创建时,这个构造函数 将会把它的属性prototype赋给新对象的内部属性__proto__。这个__proto__被这个对象用来查找它的属性。

你也可以通过prototype来给所有对象添加共用的函数。这有一个好处:你不需要每次在构造一个对象的时候创建并初始化这个函数。为了解释这一点,让我们重新来看Example DT9并使用prototype来重写它:

用prototype给对象添加函数

Example PT3

CODE:

function Employee(name, salary)
{
this.name=name;    
this.salary=salary;
}
Employee.prototype.getSalary=function getSalaryFunction()
{
return this.salary;
}
Employee.prototype.addSalary=function addSalaryFunction(addition)
{
this.salary=this.salary+addition;
}

 我们可以象通常那样创建对象:

CODE:

var boss1=new Employee("Joan", 200000);
var boss2=new Employee("Kim", 100000);
var boss3=new Employee("Sam", 150000);

并验证它:

CODE:

alert(boss1.getSalary()); // 输出 200000
alert(boss2.getSalary()); // 输出 100000
alert(boss3.getSalary()); // 输出 150000

这里有一个图示来说明prototype是如何工作的。这个对象的每一个实例(boss1, boss2, boss3)都有一个内部属性叫做__proto__,这个属性指向了它的构造器(Employee)的属性prototype。当你执行 getSalary或者addSalary的时候,这个对象会在它的__proto__找到并执行这个代码。注意这点:这里并没有代码的复制(和 Example DT8的图表作一下对比)。

谈谈js中的prototype及prototype属性解释和常用方法

Javascript 相关文章推荐
JS模拟多线程
Feb 07 Javascript
DLL+ ActiveX控件+WEB页面调用例子
Aug 07 Javascript
关于firefox的ElementTraversal 接口 使用说明
Nov 11 Javascript
基于jQuery的倒计时插件代码
May 07 Javascript
JS判断元素为数字的奇异写法分享
Aug 01 Javascript
原生JavaScript制作微博发布面板效果
Mar 11 Javascript
vue2.0获取自定义属性的值
Mar 28 Javascript
JavaScript的六种继承方式(推荐)
Jun 26 Javascript
Node.js使用Angular简单示例
May 11 Javascript
Angular CLI 使用教程指南参考小结
Apr 10 Javascript
js的继承方法小结(prototype、call、apply)(推荐)
Apr 17 Javascript
node.js使用net模块创建服务器和客户端示例【基于TCP协议】
Feb 14 Javascript
Bootstrap每天必学之下拉菜单
Nov 25 #Javascript
使用Javascript写的2048小游戏
Nov 25 #Javascript
Jquery-1.9.1源码分析系列(十一)之DOM操作
Nov 25 #Javascript
Bootstrap每天必学之栅格系统(布局)
Nov 25 #Javascript
jQuery实现宽屏图片轮播实例教程
Nov 24 #Javascript
jquery利用拖拽方式在图片上添加热链接
Nov 24 #Javascript
jquery中checkbox使用方法简单实例演示
Nov 24 #Javascript
You might like
超强分页类2.0发布,支持自定义风格,默认4种显示模式
2007/01/02 PHP
PHP chmod 函数与批量修改文件目录权限
2010/05/10 PHP
怎样给PHP源代码加密?PHP二进制加密与解密的解决办法
2013/04/22 PHP
PHP统计二维数组元素个数的方法
2013/11/12 PHP
php使用正则验证中文
2016/04/06 PHP
php版微信支付api.mch.weixin.qq.com域名解析慢原因与解决方法
2016/10/12 PHP
Yii针对添加行的增删改查操作示例
2016/10/18 PHP
在laravel中实现将查询的对象转换为多维数组的函数
2019/10/21 PHP
javascript学习笔记(二十) 获得和设置元素的特性(属性)
2012/06/20 Javascript
javaScript复制功能调用实现方案
2012/12/13 Javascript
js验证模型自我实现的具体方法
2013/06/21 Javascript
JavaScript获取table中某一列的值的方法
2014/05/06 Javascript
jquery 为a标签绑定click事件示例代码
2014/06/23 Javascript
JS实现超炫网页烟花动画效果的方法
2015/03/02 Javascript
jQuery超赞的评分插件(8款)
2015/08/20 Javascript
node+vue实现用户注册和头像上传的实例代码
2017/07/20 Javascript
JS排序算法之冒泡排序,选择排序与插入排序实例分析
2017/12/13 Javascript
详解vuex commit保存数据技巧
2018/12/25 Javascript
[02:51]2014DOTA2国际邀请赛 IG战队官方纪录片
2014/07/21 DOTA
python套接字流重定向实例汇总
2016/03/03 Python
教你用Type Hint提高Python程序开发效率
2016/08/08 Python
Python 爬虫学习笔记之正则表达式
2016/09/21 Python
Python实现的质因式分解算法示例
2018/05/03 Python
使用sklearn进行对数据标准化、归一化以及将数据还原的方法
2018/07/11 Python
详解爬虫被封的问题
2019/04/23 Python
Python面向对象之多态原理与用法案例分析
2019/12/30 Python
浅谈keras中的目标函数和优化函数MSE用法
2020/06/10 Python
python分布式爬虫中消息队列知识点详解
2020/11/26 Python
使用Canvas操作像素的方法
2018/06/14 HTML / CSS
在线购买澳大利亚设计师手拿包和奢华晚装手袋:Olga Berg
2019/03/20 全球购物
应届毕业生自我鉴定范文
2013/12/27 职场文书
会计专业应届生自荐信
2014/02/07 职场文书
给老师的检讨书
2014/02/11 职场文书
公务员政审个人鉴定
2014/02/25 职场文书
2015年幼儿园中班工作总结
2015/04/25 职场文书
开发一个封装iframe的vue组件
2021/03/29 Vue.js