`
lgx2351
  • 浏览: 170723 次
  • 性别: Icon_minigender_1
  • 来自: 福州
社区版块
存档分类
最新评论

js学习笔记3-构造函数、类和原型

阅读更多

3. 构造函数、类和原型
总述:
对象是我们很熟悉的,常在程序中用它。那么,如何来区分一个对象与另一个对象的区别呢?类就做到了这点,对象是类的一个实例。
Js中的类与java的类不太一样,但是它构造函数和原型来来支持类。
3.1构造函数
我们在程序里使用对象时常常先new一个object,然后再给这个object赋属性,然后再使用这个object来实现我们想要的功能。很经常的,new一个无参数的object,我们这样写:

var o = {};

 
其实它的实现与下面的代码是一样的:

var o = new object();

 
在后面的写法中,new 后面的object()就是一个构造函数,就像在程序里我们常常自定义构造函数,设置它的prototype,再new一样。那么什么是构造函数呢?
构造函数是设计来和new一起使用的函数。new后,就把新的对象作为this关键字的值来传递了。
构造函数的作用是什么呢?它是初始化一个新创建的对象,设置在使用这个对象之前的所有属性。
可以定义自己的构造函数(常用),只需要编写一个为this添加属性的函数就可以了。如下的例子:

function Rectangle(w,h){
 this.w = w;
 this.h = h;
}
var rec1 = new Rectangle(1,1);//var rec1 = {w:1,h:1}
var rec1 = new Rectangle(2,2);//var rec2 = {w:2,h:2}

 

以上代码注意:
1、 注释里的效果也是一样的。那么我们为什么还要定义构造函数呢?构造函数方便你new多个对象,而注释里的写法是只需要使用一次这样的对象。
2、 从上面的代码可以看出:通过定义一个函数(构造函数),其实就定义了对象的一个类。
3、 上述类new的对象,都保证了初始化了w和h的值。根据传入构造函数的w和h的数值的不同,可以得到不同w和h值的对象,但这些对象都有相同的属性(如计算面积的方法都相同等)。
3.2原型与继承
在上面代码的例子中,我们如果要计算rec1这个对象的面积,需要这样做:

rec1.area = function(){
 return this.w * this.h
}
var a = rec1.area();

 

在上面这种情况下,如果rec2也要得到它的面积,也要定义一个它自己的area函数值。其实,所有的rectangle对象的计算面积的方法是一样的,我们可以把这个方法写在构造函数里。如下:

function Rectangle(w,h){
 this.w = w;
 this.h = h;
 this.area = function(){this.w*this.h}
}

 
这时候用这个新的构造函数后new的对象就可以直接用rec1.area()来得到它的面积了。
但是这里引出了一个问题,什么问题呢?
如果用上面的构造函数的放,每new一个矩行对象,都会初始化三个属性,这三个属性中除了w和h是每个对象不同的,area属性却是每个对象都指向同一个函数functiion。
这就引出了原型。可以把area方法放在这个类的原型对象里。
1、原型对象的任何属性,都表现为以它为原型的对象的属性。这句话比较难理解,好好理解一下,其实它说的是js中的对象都从它的原型里继承属性。
2、当我们new一个对象时,其实在内部也设置了这个对象的原型,这个对象的原型就是它的构造函数的prototype的值。
3、所有的函数都有一个prototype属性。也就是你定义一个函数后,prototype就被自动创建和初始化了。
4、增加给原型的任何属性,都会成为被构造函数初始化的对象的属性。
如上面的例子中,我们可以这样写:

function Rectangle(w,h){
 this.w = w;
  this.h = h;
}
Rectangle.prototype={
 area:function(){
  return this.w * this.h
 }
}

 
上面的代码中,w和h在每个对象实例中都不同;把area属性放在原型里说明了:原型对象与构造函数相关,并且用构造函数new出来的每个实例对象都从原型那里继承了一份相同的一组属性。
这也说明了,原型对象是放置方法和其它不变属性的理想的地方。
原型的概念也就引出了继承这个概念。
使用原型有两个好处:
1、 使用原型可以减少每new一个对象所占有的内存,因为new的不同的对象可以同时继承原型的不同的属性。
2、 即使是对象创建之后才增加到原型中的方法,对象也继承它。这就说明:可以为已有的类添加新的方法。
第二点常用,比如某个类是别人写好的,或是内建的,你需要扩展它,就可以增加一个这个类的prototype的属性。(但是对于内建类,最好不要这么做,因为你扩展了,所有的这个类的实例都会因此而多个属性)
3.3 继承的属性的读和写
我们知道:每个类都有原型对象,原型对象带有一组属性,这组属性可以被这个类的所有多个实例所继承。所以,在读一个类的属性和写一个类的属性时,需要执行一种不对称。也就是当读一个o的p属性时,会先到o中看是否有p的属性,如果没有,则到原型中去看。但当写一个o的p属性值时,并不用原型。为什么呢?因为如果用原型的话,会改变整个类对象的p的值。
因此,属性继承只在读取属性值时发生,而在写入属性值时不发生。因此,如果我们设置了o的p的值,而当这个p是从原型那里继承来的时,其实o会直接在自身创建出一个p属性。这样,当读取p属性值时,就不需要到原型中去找,只需要读取出自身的p属性的值就好了。这就好像o的属性p“遮盖”或“隐藏”了原型对象中的属性p。例子如下:

function Circle(x,y,r){
 this.x = x;
 this.y = y;
 this.r = r;
}
Circle.prototype={
 pi :3.1415926,
 area:funciton(){
  return this.pi*this.r*this.r
 }
}
var c1 = new Circle(1,1,1);
var c2 = new Circle(2,2,2);
//
c1.area();//area并不在c1中,从原型中去找,就好像这是c1自身的属性一样。这种写法我们在程序中很常用。
c1.pi = 4;//设置pi的值,pi在原型中,并不在c1自身的属性中,它把作为c1的一个自身的新属性来创建。改变原型的属性值,这种情况比较少,我们一般去读取它。
var a= c1.pi*c1.r*c1.r//这时候,pi和r都在c1自身内有。
var a= c2.pi*c2.r*c2.r//这时候,pi在c2的原型里去读,r都在c2自身读取。
因为原形属性是一个类的所有对象共享的属性,所以原型成为定义方法的理想场所。

 
3.4 Js中模拟类:
我们知道,对象是包含各种具有名字的数据片断的数据结构,也可以包含对这些数据片断进行操作的方法。对象把相关的值和方法组织到一起,这样增强了代码了模块性和可复用性,使得编程更加容易。
Js中的对象可以有任意多的属性,且属性可以动态地添加,但java的对象就不是这样,java中的每一个对象都有组预定义的属性,这些属性并不能动态地添加的。
在java的类中,确切地指定了字段,及方法的同时,会有一个类方法名,但是js不会有一个正式的类名,它只是通过构造函数和原型来模拟类。
Js和java的类都可以有多个对象,一个对象就是类的一个实例。
一个java类的类成员有实例属性、实例方法、类属性、类方法。下面分别来说明:
实例属性:
每个对象都拥有它的实例属性的一份拷贝,实例属性都是通过对象来访问。如:
r1.w
在Retangle类中,每个Retangle对象都有一个w属性指定了它的宽度。
默认情况下,js的任何对象属性都是一个实例属性。然而为了真实地模拟面象对象的类,我们说实例属性是由构造函数创建和初始化的属性。
实例方法:
实例方法在特定的对象上被调用。如:
r1.eara()
实例方法里通过this来引用调用它的对象。我们千万不要理解成实例方法是每个对象都有一份自己的私有拷贝,实例属性是每个对象都有有一份自己的私有拷贝,但实例方法却相反,这是每个对象所共享的。我们一般把实例方法放在构造函数的原型上来定义,通过这种方式,这样,通过这个构造函数实例化的对象都共享和继承了这个方法。
类属性:
类属性是与一个类自身相关的属性,而不是和这个类的每个实例相关的属性。类属性通过自身来调用。
不管创建了多少份这个类的实例,类属性只有一份。类属性本质上是全局的。
在js里,我们通过定义构造函数的自身的一个属性来定义类属性。
类方法:
类方法是与一个类自身相关,而不是与类的实例相关的方法。类方法通过自身来调用。
要定义一个类方法,只需要把这个相应的函数定义成为构造函数的一个属性就可以了。
类方法的this并不指向类的任何具体的实例,而是引用构造函数自身。
代码例子如下:

functinn Circle(x,y,r){
 //这里的x,y,r都是实例属性
 this.x = x;
 this.y = y;
 this.r = r;
}
//这里的pi是类属性
Circle.pi = 3.1415

Circle.prototype={
 //area()方法是实例方法
 area:function(){
  return Circle.pi * this.r*this.r
 }
}
//max()方法是个类方法,传入a和b两个类实例进行比较,并征对某个具体的实例
Circle.max = function(a,b){
 if(a.r>b.r) return a;
 else return b;
}

 

2
0
分享到:
评论

相关推荐

    Javascript学习笔记之函数篇(五) : 构造函数

    Javascript 中的构造函数与其他语言相比也是不同的。任何通过关键字 new 调用的函数都可以当做构造函数。 在构造函数体内,this 指向新创建的对象。如果构造函数体内没有显示的 return 表达式,那么我们就默认返回 ...

    javascript学习笔记.docx

    10) 每个类都有一个原型(prototype)对象,它具有一套属性和方法,用来共享一个类的方法和常量,还有一个constructor的属性引用构造函数。 11) JavaScript中面向对象的特性: a) 实例属性:在构造函数创建或初始化...

    JS学习笔记之原型链和利用原型实现继承详解

    本文实例讲述了JS学习笔记之原型链和利用原型实现继承。分享给大家供大家参考,具体如下: 原型链 原型链是一种关系,实例对象和原型对象之间的关系,关系是通过原型(__proto__)来联系的 实例对象中有__proto__,是...

    javascript-learning-road:js学习笔记

    类笔记 类继承 利用super()来调用父类的构造函数。...构造函数原型prototype(原型对象) 1.构造函数通过原型分配的函数是所有对象所共享的。 2.每个一个构造函数都有一个原型属性,指向另一个对象。这个prototyp

    Ruffy javascript 学习笔记

    1,javascript的原型模型:prototype 在实现面向对象,(像是定义一个类的时候)需要一个构造函数来定义对象的成员,而方法去依附在该构造函数的原型上. 2,javascript中,为了实现继承,必须将子类构造函数的...

    javascript学习笔记(五)原型和原型链详解

    在函数内部定义的变量和函数,如果不对外提供接口,外部是无法访问到的,也就是该函数的私有的变量和函数。 代码如下: [removed]  function Test(){  var color = “blue”;//私有变量  var fn = function() //...

    javascrip上百技术总集

    -(4) JavaScript面向对象的支持--(5) JavaScript面向对象的支持--(6) JavaScript精简学习1:基础知识 JavaScript精简学习2:浏览器输出 JavaScript精简学习3:图像 JavaScript精简学习4:表单 ...

    《javascript设计模式》学习笔记二:Javascript面向对象程序设计继承用法分析

    构造函数继承(类式继承,组合继承,伪经典继承) b.原型继承 c.原型赋值(遍历)继承(寄生式继承) 2.构造函数继承 所谓的构造函数继承,就是通过创建一个新对象,调用父类构造函数实现的一种继承

    Javascript学习笔记8 用JSON做原型

    代码如下: 代码如下: [removed] var People = { name: “kym”, age: 21, SayHello: function () { alert(... 首先,在一个JSON对象有一个构造方法是不可能的了,那么我们就做一个简单的“工厂”吧,写一个

    JavaScript函数、闭包、原型、面向对象学习笔记

    断言 单元测试框架的核心是断言方法,通常叫assert()。 该方法通常接收一个值–需要断言的值,以及一个表示该断言目的的描述。 如果该值执行的结果为true,断言就会通过; ...否则,断言就会被认为是失败的。...

    作为前端,你需要懂得javascript实现继承的方法

    现在我们可以利用ES6的extends方法实现继承,如果想了解更多有关ES6实现的继承请查看《ES6学习笔记(二):教你玩转类的继承和类的对象》,在这里不再做更多的介绍。 文章目录1. call()2. 借用构造函数继承父类型...

    HTML笔记.docx

    HTML专用学习笔记,包含HTML+CSS+JavaScript知识点的内容,将三部分划分出来进行整理,有HTML的简介,css的简介,css选择器,HTML文本标签和样式,盒子模型,高度塌陷的问题,JavaScript的简介,基本语法,对象介绍...

    mosh-ultimate-javascript-mastery-series-part-2:Mosh编写的代码-最终JavaScript精通系列-第2部分

    构造函数(5:36) 构造器属性(2:24) 函数就是对象(4:47) 值与引用类型(5:49) 添加或删除属性(3:53) 枚举属性(2:50) 抽象(4:02) 私有属性和方法(4:05) 吸气剂和二传手(5:36) 备忘单 运动-...

    javascript原型链学习记录之继承实现方式分析

    本文实例讲述了javascript原型链学习记录之继承实现方式。分享给大家供大家参考,具体如下: 在慕课网学习继承的笔记: 继承的几种方式: ① 使用构造函数实现继承 function Parent(){ this.name = 'parent'; } ...

    JavaScript继承学习笔记【新手必看】

    JavaScript作为一个面向对象语言(JS是基于对象的),可以实现继承是必不可少的,但是由于本身并没有类的概念,所以不会像真正的面向对象编程语言通过类实现继承,但可以通过其他方法实现继承。实现继承的方法很多,...

    javascript学习笔记(九) js对象 设计模式

    1.创建对象 代码如下: var person = new Object(); person.name = “RuiLiang”; person.age = 30; person.job = “Teacher”; person.sayName = function () { alert(this.name); }; person.sayName();...

    JavaScript学习笔记整理_简单实现枚举类型,扑克牌应用

    //构造函数 var Enumeration = function(){throw 'can not Instantiate Enumerations';}; //重写原型并将原型赋值给变量proto var proto = Enumeration.prototype = { constructor:Enumeration, toString:...

    JavaScript高级程序设计(第3版)学习笔记10 再访js对象

    (1)对象属性和特性  什么是属性(Property),什么是特性(Attribute),这有什么区别?我不想也不会从语义学上去区分,对于这系列文章来说,属性就是组成对象的一个部分,广义上也包括对象的方法,而特性则是指...

    JavaScript 继承详解及示例代码

    有些知识当时实在看不懂的话,可以先暂且放下,留在以后再看也许就能看懂了...链接: [学习笔记] 小角度看JS原型链 从原文中小摘几句 构造函数通过 prototype 属性访问原型对象 实例对象通过 [[prototype]] 内部属性

Global site tag (gtag.js) - Google Analytics