戏说javascript原型(prototype)实现面向对象

原型prototype

JS中的方法分为三类:类方法,对象方法,原型方法

比如:一个类(Function,为对比java,以下统称为类)

function Parent(name){

this.name=name;

this.sayHello=function(){

alert(‘Hello,’+name);

}

}

Parent类中sayHello方法就是对象方法,类比java中的实例方法

那么我这样定义一个方法呢?

Parent.run=function(){

alert(‘run……’);

}

这样定义的方法是合法的,这样的方法(run)是类方法,类比java中的静态方法。

最后还可以这样定义方法:

Parent.prototype.eat = function(){

alert(‘eat too more!’);

}

这样也是合法的,这样的方法叫做原型方法。

接下来谈一谈如何调用这些方法,为方便记忆,这里也跟java作类比。

对象方法的调用:

与java相同,先有对象,然后再调用,比如:

var p1 = new Parent(‘张三’);

p1.sayHello();//打印 Hello,张三

类方法的调用:

依然与java相同,不需要创建对象,也可以直接调用,比如:

Parent.run();//打印 run……

注:java中一般类直接调用静态方法,但也可以使用实例来调用,只是不鼓励使用。js中使用实例是无法调用类方法的,这个需要牢记。

原型方法的调用:

最难理解的就是原型方法了,在java中似乎没有与之对应的元素在,其调用方法可以直接使用对象调用,比如:

p1.eat();//打印 eat too more!

也可以这样调用:

Parent.prototype.eat();//打印 eat too more!

那么原型究竟是个什么东西呢,如何进行类比呢?

既可以用类来调用,又可以用对象来调用,这个跟java中静态方法很像,java中虽然允许实例直接调用类方法,但不鼓励使用。而在JS中,是专门针对对象引入的原型,

而使用类直接调用原型方法就显得比较繁琐。这样看来,用类方法来类比原型方法也是说得通的。但要明白其间差别。

最后,用一个通俗的方式来描述原型,原型相当于在类中添加了一个容器,我们可以任意把方法和引用放置进去,使用对象调用的时候,会优先去实例中查找同名方法,如果

找不到则会去prototype方法中查找。也就是说,prototype是公用的(只有一个),只有类可以对其改变,改变之后所有的对象都可以进行引用。

出几个题,过把瘾先,对于上面的代码,添加几个功能。

Parent.sayHello= function(){

alert(‘Hello,Static Function’);

}

Parent.prototype.sayHello=function(){

alert(‘Hello,prototype,Function’);

}

这时候我的问题来了,使用如下方式调用分别打印什么?

p1.sayHello();

Parent.sayHello();

Parent.prototype.sayHello();

答案依次是:

Hello,prototype,Function //解释器会先去对象方法中查找方法,如果存在则直接使用,如果不存在,则去原型中查找

Hello,Static Function //不用多说,直接用类访问方法,只能访问到类方法

Hello,prototype,Function //这个似乎也不用多说,定义的时候就是这么定义的

下面一个简陋的表格:

方法类型| 调用方式 | 不可以如此调用 | 备注

——–|———————–|—————————|——————————————————————————

对象方法| obj.method(); | Class.method(); | 对象方法使用this定义,也可以obj.method2 = function(){}定义,但后者只能本对象可见

——–|———————–|—————————|——————————————————————————

类方法 | Class.Method(); | obj.method(); | 决不能只用对象调用类方法,这个与java区分开

——–|———————–|—————————|——————————————————————————

原型方法|obj.method(); | obj.prototype.method(); | 与对象方法重名时,对象方法会优先被调用

|Class.prototype.method;| |

——–|———————–|—————————|——————————————————————————

以下说一说继承那些事:

JS也是面向对象的,所有的数据都可以看做对象,很多东西不需要定义,直接拿来使用。而当需求高度抽象的时候,就会出现“面向过程编程”,代码冗长而不易懂。为了实现

面向对象的那些特性,我们就自定义一些类型,如上面定义的Parent,就是一个自定义类型。那么既然是面向对象了,就应该有面向对象的特性吧(封装,继承,多态)。封装就不用多说了,定义一个类型以后,所有的方法和属性都使用this来封装到类型中了(与java不同的是,js有一个原型,可以随时添加属性和方法,也可以使用类型直接添加静态的属性和方法),下面着重说一下继承和多态。

关于继承,网上有不少关于继承的方式,比如构造函数继承,原型继承,call和apply继承。

两个类:

function Parent(name){

this.name=name;

this.sayHello2Parent(){

alert(‘Hello,’+name);

}

}

function Child(name){

}

构造函数继承:

Child 类可以这样改造

function Child(name){

var p1 = new Parent();

p1.name=name;

p1.sayHello2Child=function(){

}
return p1;

}

var c1 = child(‘李四’);

这样c1具有了p1的属性和方法,且可以在Child方法中实现覆盖和隐藏。但这样的继承很明显入侵比较严重,Child方法需要进行改造,不可取。

原型继承:

Child.prototype = new Parent(‘张三’);//意思是把Parent的所有的属性和方法,拷贝给Child的原型(理解为放入其原型容器中)

Child.prototype.sayHello2Parent = function(){

alert(‘Hello,Child’);

}

这样就能够实现多态了,也就是父类型的同名方法被覆盖了。

那么如果想像java一样,调用父类的方法,如何操作呢?(java中使用super)

var p1 = new Parent(‘张三’);

var c1 = new Child(‘李四’);

p1.sayHello2Parent.call(c1);//这样可以调用到父类的方法了

最后说一说call和apply继承:

function Child(name){

Parent.call(this,name);

}

function Child(name){

Parent.apply(this,arguments);

}

以上说明了,对象方法和原型方法都可以实现继承和覆盖,现在有个问题,类方法可以实现继承和覆盖吗?

答案是:不能 这点跟java中的特性一样的,所有的static变量和方法是无法实现继承的,因此也不存在多态。

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-05 05:44:03

戏说javascript原型(prototype)实现面向对象的相关文章

javascript原型Prototype

在javaScript创建对象一文中提到过:用构造函数创建对象存在一个问题即同一构造函数的不同实例的相同方法是不一样的,所以我们用原型把构造函数中公共的属性和方法提取出来进行封装,达到让所有实例共享的目的. 接下来进一步介绍javaScript原型. 一.javaScript原型机制 1.函数与原型的关系 js中创建一个函数,就会自动创建一个prototype属性,这个属性指向函数的原型对象,并且原型对象会自动获得一个constructor(构造函数)属性,指向该函数. 举例:以前面的原型模式创

JavaScript 原型 prototype 使用经验

function Foo(){} Foo.prototype.sayName = function(){ return '初始原型'; } var foo1 = new Foo(); foo1.sayName() //'初始原型' // new 方式重写原型:切断了新实例 与 原有原型之间的连接 function Bar(){} Foo.prototype = new Bar(); // var foo2 = new Foo(); foo2.sayName(); // error 报错:找不到这

深入理解javascript原型和闭包(3)——prototype原型

转载于http://www.cnblogs.com/wangfupeng1988/p/3978131.html 既typeof之后的另一位老朋友! prototype也是我们的老朋友,即使不了解的人,也应该都听过它的大名.如果它还是您的新朋友,我估计您也是javascript的新朋友. 在咱们的第一节(深入理解javascript原型和闭包(1)——一切都是对象)中说道,函数也是一种对象.他也是属性的集合,你也可以对函数进行自定义属性. 不用等咱们去试验,javascript自己就先做了表率,人

理解javascript原型和作用域系列(3)——prototype原型

既typeof之后的另一位老朋友! prototype也是我们的老朋友,即使不了解的人,也应该都听过它的大名.如果它还是您的新朋友,我估计您也是javascript的新朋友. 在咱们的第一节(理解javascript原型和作用域系列(1)——一切都是对象)中说道,函数也是一种对象.他也是属性的集合,你也可以对函数进行自定义属性. 不用等咱们去试验,javascript自己就先做了表率,人家就默认的给函数一个属性——prototype.对,每个函数都有一个属性叫做prototype. 这个prot

Javascript中的原型prototype

prototype属性可算是JavaScript与其他面向对象语言的一大不同之处. 简而言之,prototype就是“一个给类的对象添加方法的方法”,使用prototype属性,可以给类动态地添加属性和方法,以便在JavaScript中实现“继承”的效果. 通过以此函数作为构造函数构造出来的对象都自动的拥有构造函数的prototype对象的成员属性和方法. 其中的要点是: prototype是函数(function)的一个必备属性(书面一点的说法是"保留属性")(只要是function

[js高手之路]一步步图解javascript的原型(prototype)对象,原型链

我们接着上文继续,我们通过原型方式,解决了多个实例的方法共享问题,接下来,我们就来搞清楚原型(prototype),原型链的来龙去脉. function CreateObj(uName) {             this.userName = uName;         }         CreateObj.prototype.showUserName = function(){             return this.userName;         }         va

简单理解javascript的原型prototype

原型和闭包是Js语言的难点,此文主要讲原型. 每一个方法都有一个属性是 prototype 每一个对象都有一个属性是 _proto_ 一旦定义了原型属性或原型方法,则所有通过该构造函数实例化出来的所有对象,都继承了这些原型属性和原型方法,这是通过内部的_proto_链来实现的. /* Js所有的函数都有一个prototype属性,这个属性引用了一个对象,即原型对象,也简称原型.这个函数包括构造函数和普通函数,我们讲的更多是构造函数的原型,但是也不能否定普通函数也有原型. 每一个方法都有一个属性叫

秒懂javascript的原型(prototype)对象、原型链的前世今生

在上文中我们通过原型方式,解决了多个实例的方法共享问题,接下来,我们就来搞清楚原型(prototype),原型链的来龙去脉. function CreateObj(uName) { this.userName = uName; } CreateObj.prototype.showUserName = function(){ return this.userName; } var obj1 = new CreateObj('ghostwu'); var obj2 = new CreateObj('

JavaScript之基础-16 JavaScript 原型与继承

一.JavaScript 原型 原型的概念 - 在JavaScript中,函数本身也是一个包含了方法和属性的对象 - 每个函数中都有一个prototype属性,该属性引用的就是原型对象 - 原型对象是保存共享属性值和共享方法的对象 为对象扩展属性 - 扩展单个对象的成员 - 扩展共享的属性值 - 内存图描述 删除属性 - 可以使用delete关键字删除对象的属性 自由属性与原型属性 - 自有属性:通过对象的引用添加的属性;其它对象可能无此属性;即使有,也是彼此独立的属性 emp1.job = '