<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<html>
<head>
<script type="text/javascript">
/*
总括:
javascript创建对象的模式演化:1,函数创建----》2,构造函数创建
-----》3.原型创建
*/
//第一种模式:函数创建模式
//因为js无法创建类,开发人员刚开始发明了一种函数,用函数来封装以特定接口创建
//对象的细节,如:
function createPerson(name,age,job)
{
var o = new Object();
o.name = name;
o.age = age;
o.job = age;
o.sayName = function sayName(){
alert(this.name);
};
return o;
}
function onloadFunction()
{
var person1 = createPerson("陈超阳","27","java Soft Enginner")
var person2 = createPerson("heshengnan","23","java Soft Enginner")
console.log(person1);
console.log(person2);
console.log(person1.constructor); //打印出Object
console.log(person2.constructor); //打印出Object
}
/*
函数工厂模式虽然解决了创建多个相似对象的问题,但却没有解决对象识别的问题
(即怎样知道一个对象的类型)
Person1,person2的构造函数都是Object,因此无法辨别对象的类型
随着JavaScript的发展,出现了一种新的工程模式--构造函数模式
*/
//第二种模式:构造函数模式
/*
注意:
1,该种模式没有显示创建对象也就是没有用new Object();
2,直接将属性和方法赋值给this对象。
3,没有return语句
4.函数名字的首字母是大写的(以便区分构造函数和一般函数的区别)
5,要创建Person的新实例必须使用new关键字
*/
/*
使用new 构造函数创建对象的步骤:
1,js引擎会自动创建一个对象。
2,将构造函数的作用域赋给新对象(因此this就指向了新对象)
3,执行构造函数里面的代码(为这个新对象添加属性方法);
4,返回新对象
*/
function Person(name,age,job)
{
this.name = name;
this.age = name;
this.job = job;
this.sayName = function(){
alert(this.name);
}
}
function onloadFunction2()
{
var person3 = new Person("陈超阳","27","java Soft Enginner");
var person4 = new Person("heshengnan","23","java Soft Enginner")
console.log(person3.constructor); //打印出Person(name, age, job)
console.log(person4.constructor); //打印出Person(name, age, job)
//构造函数设计之初是用来标示对象类型的,但是提到检测对象类型,还是用instanceof操作符
//要更可靠一些,我们在这个例子中创建的所有对象既是Object的实例,同时也是Person的实例
//这一点可以用instanceof操作符可以得到验证
console.log(person3 instanceof Object); //true;
console.log(person3 instanceof Person); //true;
console.log(person4 instanceof Object); //true;
console.log(person4 instanceof Person); //true;
}
//注意以这种方法创建的构造函数是定义在global对象(在浏览器中是window中的)
/*
构造函数的缺点:
构造函数虽然好用,但并非没有缺点。使用构造函数的主要问题,就是每个方法都要在每个实例上重新创建一边
。在上面的例子中。person1和person2都有一个名字叫做sayName()的方法,但这两个sayName()
方法不是同一个function实例。不要忘记了——EcmaScript中的对象,因此每定义一个函数也就实例化了
一个对象。从逻辑上讲,此时的构造函数也可以如下面定义:
*/
function Person(name,age,job){
this.name = name;
this.age = age;
this.job = job;
this.sayName = new Function(){alert(this.name)};
}
/*
从这个角度来看构造函数,更容易明白每个Person实例都包含一个不同的function实例(以显示name属性)
的本质。说明白些,以这种方式创建函数,会导致不同的作用域链和标示符解析,但创建function新实例的
机制仍然相同。因此,不用实例上的同名函数是不相同的,一下代码可以证明这一点:
console.log(person.sayName == person2.sayName);
然而,创建两个完成同样任务的function实例的确没有必要,况且有this对象在,根本不用在执行代码前就
把函数绑定到特定对象上面,大可像下面这样,通过把函数定义在构造函数外来解决这个问题:
function Person (name,age,job)
{
this.name = name;
this.age = age;
this.job = job;
this.sayName = sayName;
}
function syaName()
{
alert(this.name);
}
在这个例子中,我们把sayName()函数的定义转移到了构造函数的外部。而在构造函数内部,我们
将sayname属性值设置成等于全局函数sayName()。这样一来,由于sayName包含的是一个指向
函数的指针,因此person1和person2对象就共享了在全局作用域中定义的同一个sayName函数
这样做确实解决了两个函数做同一件事情的问题,可是新问题又来了:在全局作用域中定义的函数
实际上只能被某个对象调用,这让全局函数有点名不副实,而更让人无法接受的是,如果对象需要定义
很多函数,那么就需要定义很多个全局函数,于是我们这个自定义的引用类型就没有封装而言了,好在
这些问题可以使用原型模式解决。
*/
/*
第三:原型模型
我们创建的每个函数都有一个prototype(原型)属性,这个属性是一个指针,指向一个对象,而这个
对象的用途是包含可以由特定类型的所有实例共享的属性和方法。如果按照字面意思来理解,那么
prototype就是通过调用构造函数而创建的那个对象实例的原型对象。使用原型对象的好处是
可以让所有对象共享它所包含的属性和方法,换句话说,不必在构造函数中定义对象实例的信息,而是
可以将这些信息直接添加到这些对象上,如下面的这些例子:
*/
function Person(){}
Person.prototype.name = "chenchaoyang";
Person.prototype.age = "454";
Person.prototype.job = "soft enginner";
Person.prototype.sayName = function(){alert(this.name)};
var person1 = new Person(){};
person1.sayName();
var person2 = new Person(){};
person2.sayName();
console.log(person1.sayName = person2.sayName); //true
/*
在此,我们将sayname()方法和所有属性直接添加到了Person的prototype属性中,构造函数
变成了空函数,即使如此,也仍然可以通过调用构造函数来创建对象,而且对象还会具有相同的属性
和方法,但与构造函数模式不同的是:新对象的浙西二属性和方法是所实例共享的,换句话说,person1
和person2访问的都是同一组属性和同一个sayName函数,要理解原型模式的工作原理,必须先理解
EcmScript中原型对象的性质。
理解原型对象:
无论什么时候,只要创建了一个函数,就会根据一组特定的规则为这个函数创建一个prototype属性,
这个属性指向函数的原型对象。 在默认情况下,所有原型对象都会自动获得一个constrcutor构造函数
,这个属性包含一个纸箱prototype属性所在函数的指针。就拿全面的例子来说,Person.prototype
.construtctor指向Person,而通过这个函数,我们可以继续为原型对象添加其他属性和方法。
*/
/*
重要:访问一个对象 的属性的过程是这样的:
首先检查这个对象是否含有自身的属性(不是这个对象含有的prototype对象的属性),如果有就直接
访问。 如果没有就去这个对象的prototype对象中检查是否含有这个属性。
也就是 首先访问自己是否含有这个属性, 然后再检查这个对象的prototype中是否含有这个属性。
例如一下例子:
*/
function Person(){}
Person.prototype.name = "chenchaoyang";
Person.prototype.age = 27;
Person.prototype.job = "softWare enginner";
Person.prototype.syaName = function(){
console.log(this.name);
}
var person1 = new Person();
var person2 = new Person();
person1.name = "heshegnnan";
console.log(person1.name); //"heshegnnan"来自实例
console.log(person2.name); //"chenchaoyang"来自原型对象
/*
总结:当为对象添加一个属性时,这个属性就会屏蔽原型对象中保存的同名属性,换句话说,添加这个属性
只会阻止我们访问原型中的那个属性,但不会修改那个属性。及时这个属性设置为null,也只会在实例中
设置这个属性,而不会恢复指向原型的链接。不过,使用delete操作符则可以完全删除实例属性,从而
让我们能够重新访问原型中的属性:例如:
function Person(){};
Person.prototype.name = "chenchaoyang";
Person.prototype.age = 12;
Person.prototype.job = "softWare enginner";
Person.prototype.sayName = function sayName(){
alert(thos.name);
}
var person1 = new Person();
var person2 = new Person();
person1.name = "Greg";
alert(person1.name); //Greg 来自实例
alert(person2.name); //chenchoyang 来自原型对象
delete person1.name;
alert(person1.name); //chenchaoyang 来自原型对象
使用hanOwnProperty()方法可以检测一个属性是否存在于实例中,还是存在于原型中。
这个方法(不要忘了它是从Object继承来的)只在属性存在于对象实例中时,才会返回
true,来看看一下的例子:
function Person(){}
Person.prototype.name = "chenchaoyang";
Person.prototype.age = 22;
Person.prototype.job = "software enginner";
Person.sayName = function sayName(){
alert(this.name);
var person1 = new Person();
person1.hasOwnProperty("name"); //false
person1.name = "heshegnnan";
person1.hasOwnProperty("name"); //true
使用hasOwnProperty方法,什么时候访问的实例属性,什么时候访问的是原型属性就一清二楚了。
}
*/
</script>
</head>
<body onload="onloadFunction();onloadFunction2();">
</body>
</html>
分享到:
相关推荐
JavaScript 的演化是渐进而稳固的。历经过去十年的进程,JavaScript 在人们的认知里 已经从一门简单的玩物式的语言逐渐发展成为一门倍受推崇的编程语言,被全世界的公司和 开发者用来构造种种精彩的应用。现代...
javascript面向对象编程,JavaScript 的演化是渐进而稳固的。历经过去十年的进程,JavaScript 在人们的认知里 已经从一门简单的玩物式的语言逐渐发展成为一门倍受推崇的编程语言,被全世界的公司和 开发者用来构造...
政府补贴和成本共担如何影响平台和企业策略选择-----基于三方演化博弈.pdf
是本人制作的ppt.探讨了由图灵机到C语言到C++到函数式编程等语言变化后的语义本质。
提出一种求解0-1背包问题的改进差异演化算法。首先对差异演化算法的选择操作进行修改,得到的改进差异演化算法可以直接有效地处理约束优化问题。其次,利用一种新的区间编码映射机制,将差异演化算法扩展到求解离散...
飞行中换引擎--美团配送业务系统架构演化.27fd5270-7e52-11e6-9b91-73d05121ccd4.pdf
大数据-算法-交互式与自适应演化算法研究.pdf
是什么支撑小米数年间平地起高楼,成为全球明星企业?其为何又在中途遇到至暗时刻,调入市值缩水90%低谷,而短暂的调整后,却又能再次快速逆市崛起?短短8年时间,一个拥有完整生态的新巨头已经升起,并且即将打破...
论文研究-求解多星任务规划问题的演化学习型蚁群算法.pdf, 任务规划在成像卫星指挥控制过程中起着非常关键的作用, 在成像卫星应用系统中处于神经中枢的地位. 提出了一种...
策略模式定义了方法族,分别封装起来,让它们之间可以相互替换,此模式让算法的变化独立于使用算法的客户。 还可以那家咖啡屋,记忆里很温馨,很sugar,或许很多温馨美好的回忆都是于咖啡有关的。 我们常常说设计...
引言事件是人类社会的核心概念之一,人们的社会活动往往是事件驱动的。事件之间在时间上相继发生的演化规律和模式是一种十分有价值的知识。然而,当前无论是知识图谱还是语
1.4亿在线背后的故事-——-腾讯-QQ-IM后台架构的演化与启示.ppt
1.4亿在线背后的故事-——-腾讯-QQ-IM后台架构的演化与启示.pdf
城市是具有自组织模式的大型耗散系统, 经济和交通是其最重要的两个子系统, 两者作为城市的动力系统, 有明确的动力演化过程, 在互动演化的进程中促进城市发展。在城市自组织模式的条件下加入政府干预的他组织因素, 以...
将投资策略和红利收益纳入同一自然状态中考虑其相互影响,分析了固定投资组合策略演化稳定性的充分必要条件,在自然状态服从独立同分布和Markov过程时,给出了唯一的演化稳定投资策略, 得到了一些更加直观具体的结果....
二维图形中轴的离散演化,侯季春,刘永进,提出了一种基于反向离散轮廓演化的二维图像离散中轴演化。从一个复杂的轮廓的简化后的形状开始,不断地恢复该形状,从中构造出一
matlab开发-用PCASpucimethod无序处理数据复杂演化。SP-UCI方法是一种针对高维和复杂问题的全局优化算法。