谈谈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 相关文章推荐
jQuery学习笔记(2)--用jquery实现各种模态提示框代码及项目构架
Apr 08 Javascript
jquery实现简单的拖拽效果实例兼容所有主流浏览器
Jun 21 Javascript
JavaScript代码简单实现求杨辉三角给定行的最大值
Oct 29 Javascript
jQuery向上遍历DOM树之parents(),parent(),closest()之间的区别
Dec 02 Javascript
上传图片预览JS脚本 Input file图片预览的实现示例
Oct 23 Javascript
JS实现灵巧的下拉导航效果代码
Aug 25 Javascript
js单页hash路由原理与应用实战详解
Aug 14 Javascript
Angular简单验证功能示例
Dec 22 Javascript
Vue父子组建的简单通信之控制开关Switch的实现
Jun 04 Javascript
微信小程序在地图选择地址并返回经纬度简单示例
Dec 03 Javascript
Vue拖拽组件列表实现动态页面配置功能
Jun 17 Javascript
Element Tooltip 文字提示的使用示例
Jul 26 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
ThinkPHP之用户注册登录留言完整实例
2014/07/22 PHP
thinkphp下MySQL数据库读写分离代码剖析
2017/04/18 PHP
作为PHP程序员你要知道的另外一种日志
2018/07/30 PHP
thinkPHP框架中layer.js的封装与使用方法示例
2019/01/18 PHP
发布一个高效的JavaScript分析、压缩工具 JavaScript Analyser
2007/11/30 Javascript
比较简单的异步加载JS文件的代码
2009/07/18 Javascript
jQuery 白痴级入门教程
2009/11/11 Javascript
JS实现跟随鼠标闪烁转动色块的方法
2015/02/26 Javascript
Jquery+Ajax+PHP+MySQL实现分类列表管理(上)
2015/10/28 Javascript
javascript实现滚动效果的数字时钟实例
2016/07/21 Javascript
javascript封装addLoadEvent实现页面同时加载执行多个函数的方法
2016/07/25 Javascript
js获取地址栏中传递的参数(两种方法)
2017/02/08 Javascript
jQuery+ajax实现修改密码验证功能实例详解
2017/07/06 jQuery
Javascript快速实现浏览器系统通知
2017/08/26 Javascript
vue vantUI实现文件(图片、文档、视频、音频)上传(多文件)
2019/10/15 Javascript
openlayers4.6.5实现距离量测和面积量测
2020/09/25 Javascript
python实现百万答题自动百度搜索答案
2018/01/16 Python
django项目环境搭建及在虚拟机本地创建django项目的教程
2019/08/02 Python
使用NumPy读取MNIST数据的实现代码示例
2019/11/20 Python
Django限制API访问频率常用方法解析
2020/10/12 Python
一篇文章带你搞定Ubuntu中打开Pycharm总是卡顿崩溃
2020/11/02 Python
关于Python3的import问题(pycharm可以运行命令行import错误)
2020/11/18 Python
Pytorch - TORCH.NN.INIT 参数初始化的操作
2021/02/27 Python
推荐WEB开发者最佳HTML5和CSS3代码生成器
2015/11/24 HTML / CSS
机关门卫岗位职责
2013/12/30 职场文书
作文评语集锦大全
2014/04/23 职场文书
工作作风承诺书
2014/08/30 职场文书
在职员工证明书
2014/09/19 职场文书
高中校园广播稿
2014/10/21 职场文书
2014年纪检部工作总结
2014/11/12 职场文书
喋血孤城观后感
2015/06/08 职场文书
汽车修理厂管理制度
2015/08/05 职场文书
交通事故协议书范本
2016/03/19 职场文书
如何做好工作总结!
2019/04/10 职场文书
php7中停止php-fpm服务的方法详解
2021/05/09 PHP
解决mysql:ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO/YES)
2021/06/26 MySQL