定义类或对象

学习总结:

工厂方式

原始的方式(对象创建后动态定义对象的属性)

var oCar = new Object;
oCar.color = "blue";
oCar.doors = 4;
oCar.mpg = 25;
oCar.showColor = function() {alert(this.color);
};



创建对象 car,属性:它的颜色是蓝色,有四个门,每加仑油可以跑 25 英里。最后一个属性实际上是指向函数的指针,意味着该属性是个方法。
有一个问题,就是可能需要创建多个 car 的实例。

解决方案:工厂方式(函数封装)

function createCar(sColor,iDoors,iMpg) {var oTempCar = new Object;oTempCar.color = sColor;oTempCar.doors = iDoors;oTempCar.mpg = iMpg;oTempCar.showColor = function() {alert(this.color);};return oTempCar;
}var oCar1 = createCar("red",4,23);
var oCar2 = createCar("blue",3,25);oCar1.showColor();		//输出 "red"
oCar2.showColor();		//输出 "blue"



这使两个对象具有相同的属性,却有不同的属性值。
每次调用函数 createCar(),都要创建新函数 showColor(),意味着每个对象都有自己的 showColor() 版本。而事实上,每个对象都共享同一个函数。

在工厂函数外定义对象的方法 可避免以上问题

function showColor() {alert(this.color);
}function createCar(sColor,iDoors,iMpg) {var oTempCar = new Object;oTempCar.color = sColor;oTempCar.doors = iDoors;oTempCar.mpg = iMpg;oTempCar.showColor = showColor;return oTempCar;
}var oCar1 = createCar("red",4,23);
var oCar2 = createCar("blue",3,25);oCar1.showColor();		//输出 "red"
oCar2.showColor();		//输出 "blue"



从功能上讲,这样解决了重复创建函数对象的问题;但是从语义上讲,该函数不太像是对象的方法。

构造函数方式

function Car(sColor,iDoors,iMpg) {this.color = sColor;this.doors = iDoors;this.mpg = iMpg;this.showColor = function() {alert(this.color);};
}var oCar1 = new Car("red",4,23);
var oCar2 = new Car("blue",3,25);



第一步选择类名,即构造函数的名字。根据惯例,这个名字的首字母大写,以使它与首字母通常是小写的变量名分开。除了这点不同,构造函数看起来很像工厂函数。

与工厂方式的差别:
首先在构造函数内没有创建对象,而是使用 this 关键字。
使用 new 运算符构造函数时,在执行第一行代码前先创建一个对象,只有用 this 才能访问该对象。
然后可以直接赋予 this 属性,默认情况下是构造函数的返回值(不必明确使用 return 运算符)。

现在,用 new 运算符和类名 Car 创建对象,就更像 ECMAScript 中一般对象的创建方式了。
就像工厂函数,构造函数会重复生成函数,为每个对象都创建独立的函数版本。
不过,与工厂函数相似,也可以用外部函数重写构造函数,同样地,这么做语义上无任何意义。这正是下面要讲的原型方式的优势所在。

原型方式

function Car() {
}Car.prototype.color = "blue";
Car.prototype.doors = 4;
Car.prototype.mpg = 25;
Car.prototype.showColor = function() {alert(this.color);
};var oCar1 = new Car();
var oCar2 = new Car();



该方式利用了对象的 prototype 属性,可以把它看成创建新对象所依赖的原型。
这里,首先用空构造函数来设置类名。然后所有的属性和方法都被直接赋予 prototype 属性。

在这段代码中,首先定义构造函数(Car),其中无任何代码。
接下来的几行代码,通过给 Car 的 prototype 属性添加属性去定义 Car 对象的属性。
调用 new Car() 时,原型的所有属性都被立即赋予要创建的对象,意味着所有 Car 实例存放的都是指向 showColor() 函数的指针。
从语义上讲,所有属性看起来都属于一个对象,因此解决了前面两种方式存在的问题。
此外,使用这种方式,还能用 instanceof 运算符检查给定变量指向的对象的类型。

alert(oCar1 instanceof Car);	//输出 "true"



原型方式的问题
这个构造函数没有参数。
使用原型方式,不能通过给构造函数传递参数来初始化属性的值,因为 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() {alert(this.color);
};var oCar1 = new Car();
var oCar2 = new Car();oCar1.drivers.push("Bill");alert(oCar1.drivers);	//输出 "Mike,John,Bill"
alert(oCar2.drivers);	//输出 "Mike,John,Bill"



属性 drivers 是指向 Array 对象的指针,该数组中包含两个名字 "Mike" 和 "John"。
由于 drivers 是引用值,Car 的两个实例都指向同一个数组。
这意味着给 oCar1.drivers 添加值 "Bill",在 oCar2.drivers 中也能看到。
输出这两个指针中的任何一个,结果都是显示字符串 "Mike,John,Bill"。
由于创建对象时有这么多问题,需要联合使用构造函数和原型方式。

混合的构造函数/原型方式

function Car(sColor,iDoors,iMpg) {this.color = sColor;this.doors = iDoors;this.mpg = iMpg;this.drivers = new Array("Mike","John");
}Car.prototype.showColor = function() {alert(this.color);
};var oCar1 = new Car("red",4,23);
var oCar2 = new Car("blue",3,25);oCar1.drivers.push("Bill");alert(oCar1.drivers);	//输出 "Mike,John,Bill"
alert(oCar2.drivers);	//输出 "Mike,John"



联合使用构造函数和原型方式,就可像用其他程序设计语言一样创建对象。
这种概念非常简单,即用构造函数定义对象的所有非函数属性,用原型方式定义对象的函数属性(方法)。
结果是,所有函数都只创建一次,而每个对象都具有自己的对象属性实例。

现在就更像创建一般对象了。
所有的非函数属性都在构造函数中创建,意味着又能够用构造函数的参数赋予属性默认值了。
因为只创建 showColor() 函数的一个实例,所以没有内存浪费。
此外,给 oCar1 的 drivers 数组添加 "Bill" 值,不会影响到 oCar2 的数组,所以输出这些数组的值时,oCar1.drivers 显示的是 "Mike,John,Bill",而 oCar2.drivers 显示的是 "Mike,John"。
因为使用了原型方式,所以仍然能利用 instanceof 运算符来判断对象的类型。

动态原型方法

function Car(sColor,iDoors,iMpg) {this.color = sColor;this.doors = iDoors;this.mpg = iMpg;this.drivers = new Array("Mike","John");if (typeof Car._initialized == "undefined") {Car.prototype.showColor = function() {alert(this.color);};Car._initialized = true;}
}



动态原型方法的基本想法与混合的构造函数/原型方式相同,即在构造函数内定义非函数属性,而函数属性则利用原型属性定义。
唯一的区别是赋予对象方法的位置。

直到检查 typeof Car._initialized 是否等于 "undefined" 之前,这个构造函数都未发生变化。
这行代码是动态原型方法中最重要的部分。
如果这个值未定义,构造函数将用原型方式继续定义对象的方法,然后把 Car._initialized 设置为 true。
如果这个值定义了(它的值为 true 时,typeof 的值为 Boolean),那么就不再创建该方法。
简而言之,该方法使用标志(_initialized)来判断是否已给原型赋予了任何方法。
该方法只创建并赋值一次,传统的 OOP 开发者会高兴地发现,这段代码看起来更像其他语言中的类定义了。

混合工厂方式

这种方式通常是在不能应用前一种方式时的变通方法。
它的目的是创建假构造函数,只返回另一种对象的新实例。
这段代码看起来与工厂函数非常相似:

function Car() {var oTempCar = new Object;oTempCar.color = "blue";oTempCar.doors = 4;oTempCar.mpg = 25;oTempCar.showColor = function() {alert(this.color);};return oTempCar;
}



与经典方式不同,这种方式使用 new 运算符,使它看起来像真正的构造函数:

var car = new Car();



由于在 Car() 构造函数内部调用了 new 运算符,所以将忽略第二个 new 运算符(位于构造函数之外),在构造函数内部创建的对象被传递回变量 car。
这种方式在对象方法的内部管理方面与经典方式有着相同的问题。
强烈建议:除非万不得已,还是避免使用这种方式。

-------------------------------------
如前所述,目前使用最广泛的是混合的构造函数/原型方式。
此外,动态原始方法也很流行,在功能上与构造函数/原型方式等价。
可以采用这两种方式中的任何一种。
不过不要单独使用经典的构造函数或原型方式,因为这样会给代码引入问题。

转载于:https://www.cnblogs.com/hiuman/p/7347414.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/256416.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

七桥问题

怎么不重复地走完连接两座岛和陆地的七座桥? 简化为以下: 答案是不能走完的。 奇点:这个点有奇数条线汇聚于此 偶点:这个点有奇数条线汇聚于此 七桥问题——一笔画问题 若一个图形全部是偶点或者只有2个奇点(没有…

office2016打开PPT出现解决VBE6EXT.OLB不能被加载问题的解决办法

第一步 打开路径C:\Program Files (x86)\Microsoft Office\root\VFS\ProgramFilesCommonX86\Microsoft Shared\VBA。找到VBA只要是默认安装路径均一样。 第二步 打开VBA6找到VBE6EXT.OLB将其复制到VBA7.1中。 第三步 打开VBA7.1找到VBE7.DLL将其复制到VBA6中。 第四步…

20151118小问题

1.模板引擎 百度百科:模板引擎(这里特指用于Web开发的模板引擎)是为了使 用户界面与业务数据(内容)分享而产生的,它或以生成特定格式的文档,用于网站的模板引擎就会产生一个标准的HTML文档. 目的:生成一个标准的HTML文档. 概念:模板引擎不属于特定技术领域,它是跨领域跨平台的概…

机器学习——人工神经网络之发展历史(神经元数学模型、感知器算法)

目录 一、神经元的数学模型 ​ 二、感知器算法(SVM算法前身) 1、目的 2、流程 >>>问题1:下图w和b的调整是什么意思? 3、算法的有效性验证 1)原算法 2)增广矩阵 3)修改后的算法…

PHP 基础知识-数组

PHP 的数组主要分为: 索引数组 - 带有数字索引的数组关联数组 - 带有指定键的数组多维数组 - 包含一个或多个数组的数组 索引数组:有两种创建索引数组的方法:索引是自动分配的(索引从 0 开始): 第一…

打开word2016总是出现很抱歉,此功能看似中断需要修复。。问题解决办法

第一步 打开运行窗口,在电脑桌面左下角有个圆圈点击进去,输入regedit,即可进入。 第二步 打开HKEY_CURRENT_USER中的SOFTWARE 第三步 找到HKEY_CURRENT_USER\SOFTWARE\Microsoft\Office\16.0\Word\Options项如图红色箭头标示。然后点击O…

机器学习——人工神经网络之多层神经网络(多层与三层)

目录 一、多层神经网络 1、多层神经网络数学模型 2、数学模型中的非线性函数fai 1)非线性函数fai存在的意义 2)非线性函数fai具体是什么? 3、多层神经网络与单层神经网络的区别与改进 1)单层神经网络数学模型 2&#xff0…

noip2012-day2-t2

【问题描述】 在大学期间,经常需要租借教室。大到院系举办活动,小到学习小组自习讨论,都需要向学校申请借教室。教室的大小功能不同,借教室人的身份不同,借教室的手续也不一样。 面对海量租借教室的信息,我…

机器学习——人工神经网络之后向传播算法(BP算法)

目录 一、后向传播算法的本质——梯度下降法求局部极值 1、w迭代公式的合理性

获取视图的宽高

1 view.measure(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT); 2 int width view.getMeasuredWidth(); 3 int height view.getMeasuredHeight(); 转载于:https://www.cnblogs.com/cmgrass/p/4978222.html

排序算法02--冒泡排序

思路:冒泡排序 就是把大的数一个个沉到下面,当然也可以是把小的数一个个浮到上面。 在最外层需要比较n-1次,因为n-1个大的数被沉到了下面,剩下一个自然就是最小的数了。 在这n-1次的里层,还需要亮亮相互比较&#xff0…

机器学习——人工神经网络之参数设置(BP算法)

目录 一、复习(BP算法) 二、训练模型的建议 三、参数设置内容 1、随机梯度下降(SGD)

关于▲的各种交点

对于△ABC证明: ①三角形的三条中线交于一点: 等腰三角形:作中线BD、CE与AC、AB交于D、E,相交于O,连接AO并延长交BC于F; 证△ABD全等于△ACE,再证△EBO全等于△D…

javaScript获取url中的参数

var urlTools {//获取RUL参数值getUrlParam: function(name) { /*?videoIdidentification */var params decodeURI(window.location.search); /* 截取?号后面的部分 index.html?actdoctor,截取后的字符串就是?actdoctor */var reg …

机器学习——支持向量机SVMpython实现

一、SVM理论 可见以下文章: 《机器学习——支持向量机SVM之线性模型》 《机器学习——支持向量机SVM之非线性模型低维到高维映射》 《机器学习——支持向量机SVM之非线性模型原问题与对偶问题》 《机器学习——支持向量机SVM之非线性模型原问题转化为对偶问题》…

琐碎易错点

1.font-size 设置的是字体的高 2.浏览器内核: 主流浏览器   内核 IE       trident Firfox     Gecko Chorme    Webkit(原来)/blink(现在) Safari     Webkit(苹果公司独立研发的&a…

Python安装Jupyter Notebook配置使用教程

原文见:https://blog.csdn.net/qq_27825451/article/details/84427269 一、什么是jupyter 1、简介: jupyter notebook是一种 Web 应用,能让用户将说明文本、数学方程、代码和可视化内容全部组合到一个易于共享的文档中。它可以直接在代码旁…

ExtJS4.2学习(10)分组表格控件--GroupingGrid(转)

鸣谢网址:http://www.shuyangyang.com.cn/jishuliangongfang/qianduanjishu/2013-11-17/179.html --------------------------------------------------------------------------------------------- 分组表格控件在我们的开发中经常被用到,GroupingGrid…

九个Console命令,让js调试更简单

一、显示信息的命令 1: <!DOCTYPE html>2: <html>3: <head>4: <title>常用console命令</title>5: <meta http-equiv"Content-Type" content"text/html; charsetutf-8" />6: </head>7: <body>8: …

numpy——axis

size()和max()中的含义 以前我理解axis0代表行&#xff0c;axis1代表列&#xff1b; 但是这种含义在函数size()和max()中恰恰相反&#xff1b; 其实不是这样的&#xff0c;我们回到单词axis本身&#xff0c;它的意思是“轴”&#xff0c;没错轴就是代表一个方向&#xff0c;像…