JS中prototype详解

JS中的prototype是JS中比较难理解的一个部分

 

本文基于下面几个知识点:

 

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>

转载自 点击打开链接
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: prototype是JavaScript的一个关键属性,每一个函数对象都有一个prototype属性。在JavaScript,对象是通过构造函数创建的,而prototype属性就是用来指向该构造函数的原型对象。 原型对象是一个普通的对象,它包含了可以被实例对象共享的属性和方法。当我们创建一个实例对象时,实例对象会通过__proto__属性链接到构造函数的原型对象上,从而实现了属性和方法的继承。 通过原型对象,我们可以为实例对象添加公共的属性和方法。当实例对象需要调用某个属性或方法时,如果实例对象自身不存在这个属性或方法,它会自动在原型对象查找。这样就实现了属性和方法的共享和复用,提高了代码的效率。 可以通过调用构造函数的prototype属性来访问原型对象,我们可以在原型对象上添加属性和方法。例如,可以通过给Array.prototype添加方法来扩展数组对象的功能,也可以给Object.prototype添加方法来扩展所有对象的功能。 需要注意的是,原型对象是共享的,当我们修改原型对象上的属性或方法时,所有的实例对象都会受到影响。因此,在修改原型对象时需要谨慎,避免对已有的对象造成不必要的影响。 总结来说,prototype属性是JavaScript用于实现继承和共享属性的关键属性,它定义了构造函数的原型对象,使得所有通过该构造函数创建的实例对象都能够共享原型对象上的属性和方法。通过原型对象,我们可以为实例对象添加公共的属性和方法,提高代码的复用性和效率。 ### 回答2: prototype属性是JavaScript每个对象都拥有的一个属性,它是一个指针,指向该对象的原型。原型是一个普通的对象,它包含了一些可被该对象实例共享的属性和方法。 通过使用prototype属性,我们可以为对象定义共享的属性和方法。当我们创建一个对象的实例时,该对象实例将会从其原型继承这些共享的属性和方法。 在JavaScript,对象的原型是通过构造函数来创建的。在创建构造函数时,会自动为该构造函数创建一个prototype属性,并将其指向一个空对象。我们可以通过向原型对象添加属性和方法,从而为实例对象提供共享的属性和方法。 原型对象的属性和方法,可以被该构造函数创建的所有实例对象公用。当我们访问实例对象的属性或方法时,如果实例对象本身没有该属性或方法,就会通过原型链的查找,去原型对象寻找。 原型属性的优势在于节省内存。因为所有实例对象共享同一个原型对象,而不是每个实例对象都拥有一份相同的属性和方法。这样就可以大大减少内存占用。 另外,通过在原型对象定义属性和方法,还可以实现动态的属性和方法。即使在对象创建之后,我们仍然可以通过修改原型对象来为其新增属性和方法,而所有实例对象都会即刻生效。 总之,prototype属性是JavaScript用于实现对象间继承和共享属性的重要机制,它可以让我们更高效地创建对象,并且提供了灵活的方式来定义和修改对象的共享属性和方法。 ### 回答3: prototype属性是JavaScript的一个特殊属性,它是由每个函数创建的对象所共享的。每个构造函数都有一个prototype属性,它指向一个对象。 使用prototype属性可以给对象添加方法和属性,这些方法和属性可以被该构造函数创建的所有对象访问和共享。当我们创建一个新对象时,JavaScript会自动为该对象创建一个__proto__属性,它指向构造函数的prototype属性。 通过给prototype属性添加方法,我们可以在构造函数创建的每个对象共享这些方法。这么做的好处是避免了在每个对象重复创建方法的内存消耗,同时也提高了代码的可维护性。 原型继承是JavaScript的一种核心概念,它基于对象的原型链,在对象的原型链查找属性和方法。当我们访问一个对象的属性或方法时,JavaScript会先在对象本身查找,如果找不到,就会去原型链上的原型对象查找。这种属性和方法的继承关系使得JavaScript的对象可以“继承”来自原型对象的属性和方法。 通过使用构造函数和对象的原型链,JavaScript实现了类似于面向对象编程语言的继承概念。我们可以创建一个构造函数,通过它创建的对象会自动继承该构造函数的原型属性和方法。这样可以实现代码的复用和灵活性,减少重复的代码。 总结来说,prototype属性是通过构造函数创建的对象所共享的一个属性。通过给prototype属性添加方法和属性,可以实现这些方法和属性在所有对象的共享。原型继承是JavaScript实现代码复用和灵活性的一种机制,通过原型链的查找,对象可以继承来自原型对象的属性和方法。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值