四原型方式

我们创建的每一个函数都有一个通过prototype(原型)属性。这个属性是一个对象,它的用途是包括能够由特定类型

的全部实例共享的属性和方法。

逻辑上能够这么理解:prototypt通过条用构造函数而创建的那个对象的原型对象。使

用原型的优点就是能够让全部对象实例共享它所包括的属性和方法。也就是说,不必在构造函数中定义对象信息。而

是直接将这些信息加入到原型中。

原型方式利用了对象的prototype 属性。能够把它看成创建新对象所依赖的原型。这里。首先用空构造函数来设置

函数名。然后全部的属性和方法都被直接赋予prototype属性。我重写了前面的样例,代码例如以下:

function Car() { };
//将全部的属性的方法都赋予prototype属性
Car.prototype.color = "blue";
Car.prototype.doors = 4;
Car.prototype.mpg = 25;
Car.prototype.showColor = function() {
return this.color;
};
var Car1 = new Car();
var Car2 = new Car();
document.write(Car1.showColor()+"<br/>");//输出:blue
document.write(Car2.showColor());//输出:blue

在这段代码中,首先定义构造函数Car()。当中无不论什么代码。接下来的几行代码。通过给Car的 prototype 属性加入

属性去定义Car对象的属性。调用new Car()时,原型的全部属性都被马上赋予要创建的对象,意味着全部Car实例存

放的都是指向 showColor() 函数的指针。

从语义上讲,全部属性看起来都属于一个对象,因此攻克了前面的工厂方式

和构造函数方式存在的问题。

此外。使用这样的方式,还能用 instanceof 运算符检查给定变量指向的对象的类型:

<span style="font-size:18px;">document.write(Car1 instanceof Car);	//输出:true</span>

原型方式看起来是个不错的解决方式。遗憾的是,它并不尽如人意。首先,这个构造函数没有參数。

使用原型方

式,不能通过给构造函数传递參数来初始化属性的值,由于Car1和Car2的color属性都等于 "blue",doors属性都等于

4,mpg属性都等于25。

这意味着必须在对象创建后才干改变属性的默认值,这点非常令人讨厌。但还没完。真正的问

题出如今属性指向的是对象,而不是函数时。

函数共享不会造成问题,但对象却非常少被多个实例共享。请思考以下的

样例:

function Car() { };//定义一个空构造函数,且不能传递參数
Car.prototype.color = "blue";
Car.prototype.doors = 4;
Car.prototype.mpg = 25;
Car.prototype.drivers = new Array("Mike","John");
Car.prototype.showColor = function() {
return this.color;
};
var Car1 = new Car();
var Car2 = new Car();
Car1.drivers.push("Bill");
document.write(Car1.drivers+"<br/>");//输出:Mike,John,Bill
document.write(Car2.drivers);//输出 :Mike,John,Bill

上面的代码中,属性drivers是指向Array对象的指针,该数组中包括两个名"Mike"和 "John"。

因为 drivers是引用

值,Car的两个实例都指向同一个数组。这意味着给Car1.drivers加入值 "Bill",在 Car2.drivers 中也能看到。输出这两

个指针中的不论什么一个,结果都是显示字符串 "Mike,John,Bill"。因为创建对象时有这么多问题。你一定会想,是否有种

合理的创建对象的方法呢?答案是有。须要联合使用构造函数和原型方式。

五混合的构造函数/原型方式(推荐使用)

混合使用构造函数方式和原型方式。就可像用其它程序设计语言一样创建对象。这样的概念很easy。即用构造函

数定义对象的全部非函数属性,用原型方式定义对象的函数属性(方法)。结果是,全部函数都仅仅创建一次。而每一个

对象都具有自己的对象属性实例。我们重写了前面的样例。代码例如以下:

function Car(Color,Doors,Mpg) {
this.color = Color;
this.doors = Doors;
this.mpg = Mpg;
this.drivers = new Array("Mike","John");
};
Car.prototype.showColor = function() {
return this.color;
};
var Car1 = new Car("red",4,23);
var Car2 = new Car("blue",3,25);
Car1.drivers.push("Bill");
document.write(Car1.drivers+"<br/>");//输出:Mike,John,Bill
documnet.write(Car2.drivers);//输出:Mike,John

如今就更像创建一般对象了。全部的非函数属性都在构造函数中创建,意味着又可以用构造函数的參数赋予属性

默认值了。由于仅仅创建showColor()函数的一个实例,所以没有内存浪费。此外,给Car1的drivers数组加入 "Bill" 值,

不会影响到Car2的数组,所以输出这些数组的值时,Car1.drivers 显示的是 "Mike,John,Bill",而 Car2.drivers 显示的

是 "Mike,John"。由于使用了原型方式。所以仍然能利用 instanceof运算符来推断对象的类型。

这样的方式是ECMAScript採用的主要方式,它具有其它方式的特性,却没有他们的副作用。只是。有些开发人员仍觉

得这样的方法不够完美。

六动态原型方式

对于习惯使用其它语言的开发人员来说。使用混合的构造函数/原型方式感觉不那么和谐。毕竟。定义类时,大多数

面向对象语言都对属性和方法进行了视觉上的封装。

请考虑以下的 Java 类:

class Car {
public String color = "blue";
public int doors = 4;
public int mpg = 25;
public Car(String color, int doors, int mpg) {
this.color = color;
this.doors = doors;
this.mpg = mpg;
}
public void showColor() {
System.out.println(color);
}
}

Java非常好地打包了Car类的全部属性和方法。因此看见这段代码就知道它要实现什么功能,它定义了一个对象的

信息。批评混合的构造函数/原型方式的人觉得,在构造函数内部找属性,在其外部找方法的做法不合逻辑。因此,他

们设计了动态原型方法。以提供更友好的编码风格。

动态原型方法的基本想法与混合的构造函数/原型方式同样,即在构造函数内定义非函数属性。而函数属性则利用

原型属性定义。唯一的差别是赋予对象方法的位置。

以下是用动态原型方法重写的Car:

function Car(Color,Doors,Mpg) {
this.color = Color;
this.doors = Doors;
this.mpg = Mpg;
this.drivers = new Array("Mike","John");
//假设Car对象中的_initialized为undefined。表明还没有为Car的原型加入方法
if (typeof Car._initialized == "undefined") {
Car.prototype.showColor = function() {
return this.color;
};
Car._initialized = true; //设置为true。不必再为prototype加入方法
}
}
var Car1 = new Car("red",4,23);//生成一个Car对象
var Car2 = new Car("blue",3,25);
Car1.drivers.push("Bill");//向Car1对象实例的drivers属性加入一个元素
document.write(Car1.drivers+"<br/>");//输出:Mike,John,Bill
document.write(Car2.drivers);//输出:Mike,John

直到检查typeof Car._initialize是否等于"undefined"之前。这个构造函数都未发生变化。这行代码是动态原型方法

中最重要的部分。

假设这个值没有定义。构造函数将用原型方式继续定义对象的方法。然后把 Car._initialized设置为

true。假设这个值定义了(它的值为 true时,typeof 的值为Boolean)。那么就不再创建该方法。简而言之,该方法使用

标志(_initialized)来推断是否已给原型赋予了不论什么方法。该方法仅仅创建并赋值一次,传统的 OOP开发人员会高兴地发

现,这段代码看起来更像其它语言中的类定义了。

我们应该採用哪种方式呢?

如前所述。眼下使用最广泛的是混合的构造函数/原型方式。此外,动态原型方式也非常流行,在功能上与构造函

数/原型方式等价。能够採用这两种方式中的不论什么一种。只是不要单独使用经典的构造函数或原型方式,由于这样会给

代码引入问题。

总之JS是基于面向对象的一门client脚本语言,我们在学习它的面向对象技术的时候要的留意JS与

其它严谨性高的程序语言的不同。也要正确使用JS创建对象的合理的方式,推荐使用构造函数与原型方式的混合方式

创建对象实例。这样能够避免很多不必要的麻烦。

轻松学习JavaScript十二:JavaScript基于面向对象之创建对象(二)的更多相关文章

  1. 风炫安全WEB安全学习第十八节课 使用SQLMAP自动化注入(二)

    风炫安全WEB安全学习第十八节课 使用SQLMAP自动化注入(二) –is-dba 当前用户权限(是否为root权限) –dbs 所有数据库 –current-db 网站当前数据库 –users 所有 ...

  2. JavaScript学习总结(十四)——JavaScript编写类的扩展方法

    在​J​a​v​a​S​c​r​i​p​t​中​可以使​用​类的p​r​o​t​o​t​y​p​e属性来​扩​展​类的属​性​和​方​法,在实际开发当中,当JavaScript内置的那些类所提供的动态 ...

  3. 轻松学习JavaScript十二:JavaScript基于面向对象之创建对象(一)

    这一次我们深入的学习一下JavaScript面向对象技术,在学习之前,必要的说明一下一些面向对象的一些术语. 这也是全部面对对象语言所拥有的共同点.有这样几个面向对象术语: 对象 ECMA-262把对 ...

  4. JavaScript学习总结(十六)——Javascript闭包(Closure)

    原文地址: http://www.cnblogs.com/xdp-gacl/p/3703876.html 闭包(closure)是Javascript语言的一个难点,也是它的特色, 很多高级应用都要依 ...

  5. JavaScript学习总结(十八)——JavaScript获取浏览器类型与版本

    从网上找到一段使用JavaScript判断浏览器以及浏览器版本的比较好的代码,在此记录一下: 1 <script type="text/javascript"> 2 v ...

  6. Bootstrap3.0学习第二十五轮(JavaScript插件——折叠)

    详情请查看http://aehyok.com/Blog/Detail/31.html 个人网站地址:aehyok.com QQ 技术群号:206058845,验证码为:aehyok 本文文章链接:ht ...

  7. Bootstrap3.0学习第二十四轮(JavaScript插件——按钮)

    详情请查看 http://aehyok.com/Blog/Detail/30.html 个人网站地址:aehyok.com QQ 技术群号:206058845,验证码为:aehyok 本文文章链接:h ...

  8. Bootstrap3.0学习第二十三轮(JavaScript插件——警告框)

    详情请查看http://aehyok.com/Blog/Detail/29.html 个人网站地址:aehyok.com QQ 技术群号:206058845,验证码为:aehyok 本文文章链接:ht ...

  9. Bootstrap3.0学习第十八轮(JavaScript插件——下拉菜单)

    详情请查看 http://aehyok.com/Blog/Detail/25.html 个人网站地址:aehyok.com QQ 技术群号:206058845,验证码为:aehyok 本文文章链接:h ...

随机推荐

  1. Selenium2+python自动化25-js处理日历控件(修改readonly属性)【转载】

    前言 日历控件是web网站上经常会遇到的一个场景,有些输入框是可以直接输入日期的,有些不能,以我们经常抢票的12306网站为例,详细讲解如何解决日历控件为readonly属性的问题. 基本思路:先用j ...

  2. Photoshop CC 2015

    1.Ctrl 加 + -号实现放大缩小2.Ctrl+T 自由变换3.Ctrl+D 取消选区,再选择处理完后想要选中别的区域的话要取消之前选中的区域,要不然之前的区域一直都是选中状态4.F12 将文件恢 ...

  3. 用WP Super Cache和七牛为你的WordPress网站加速

    众所周知,WordPress一直都是博客建站的首选程序,而现在也有越来越多的企业网站都选择采用WordPress来搭建. WordPress虽好但其过于臃肿且响应速度慢等缺点也为站长们所诟病,目前网上 ...

  4. 发布Office 365插件

    在上一篇博客<VisualStudio 2013开发Office插件>开发完成了插件后,需要将插件发布 发布前需要: Azure 应用服务,作为Office插件的发布空间,地址是:http ...

  5. HDU 2141 Can you find it?【二分查找是否存在ai+bj+ck=x】

    Give you three sequences of numbers A, B, C, then we give you a number X. Now you need to calculate ...

  6. 树链剖分【p2568】[SDOI2011]染色

    Description 给定一颗有\(n\)个节点的无根树和\(m\)个操作,操作有\(2\)类: 1.将节点\(a\)到节点\(b\)路径上所有点染成颜色\(c\) 2.询问节点\(a\)到节点\( ...

  7. python3开发进阶-Django框架的ORM常用字段和参数

    阅读目录 常用字段 字段合集 自定义字段 字段参数 关系参数 多对多的关联关系的三种方式 一.常用字段 AutoField int自增列,必须填入参数 primary_key=True.当model中 ...

  8. 【R实践】时间序列分析之ARIMA模型预测___R篇

    时间序列分析之ARIMA模型预测__R篇 之前一直用SAS做ARIMA模型预测,今天尝试用了一下R,发现灵活度更高,结果输出也更直观.现在记录一下如何用R分析ARIMA模型. 1. 处理数据 1.1. ...

  9. duplicate symbol _gestureMinimumTranslation in:

    在真机上编译无误,在模拟器上编译报错:duplicate symbol _gestureMinimumTranslation in: /Users/Sam/Library/Developer/Xcod ...

  10. delphi执行cmd命令和bat文件

    转载地址:http://blog.csdn.net/hutao1101175783/article/details/42807063 cmd:='echo d | Xcopy '+BasePath+' ...