Javascript面向对象编程(1)-理解对象和基本属性和方法

来源:互联网 发布:网络的通信设备 编辑:程序博客网 时间:2024/05/05 11:44

大年的鞭炮响起,无疑一年又过去了,过年这几天简直了。。。。面对七大姑八大姨的追问,理智的来到了浙江过年,老家简直不能待呀,(爸妈在浙江,过年不回老家),旧的一年过去了,新的一年已经到来,面对一天天响起的烟花爆竹,心里面还是有些紧张的呀,今年就要毕业了,十几年的读书生涯就此结束了,想起来有时候就不能安心的睡觉,既然不能安心的休息,那就拿出书来看看,离开北京的时候带来一本《JavaScript高级程序设计》和《Android安全开发》,离开北京先回到老家贵州呆了两天就来浙江了,刚到浙江的时候下车就捡到一百多元钱,哎呀,新年第一金呀!过年这几天白天时而陪陪父母时而看看书,好好查缺补漏,一直做后台开发和Android开发的我对js就不是很强,所以就花了一些时间看看JavaScript方面的东西,反正是慢慢的积累,总有一天会利用好它的,其实在过年这几天好多小伙伴都发新年祝福说“大神新年快乐”,左一句大神右以及大神的,叫的我自己都有点心虚了,其实吧,数技术大神人物,不是在大神的路上,就是在大神的殿堂,路走长了,走稳了就不一样了。
这几天就看看JavaScript面向对象编程方面的东西,细细的体会了一下:
面向对象(Object-Oriented OO)的语言有一个标致,就是他们都有类的概念,而通过类可以创建任意多个具有相同属性和方法的对象,而在JavaScript中没有类的概念,因此JavaScript对象也和基于类的语言对象有所不同。
JavaScript把对象定义为:无序属性的集合,其属性可以包含基本值,对象或者是函数,严格的说就相当于对象是没有一组没有特定顺序的集合的值,对象的每一个属性和方法都有特定的名字,而每一个名字都是映射到一个值,每一个对象都是通过应用类型创建的。这些引用类型可以是原生的类型也可以是用户自定义的数据类型。
对象的理解
最简单的创建对象的方法如下所示:

var person=new Object();person.name="xiaotangdou";person.sex="男";person.age="23";person.getName=function(){alert(this.name)}

上面这个例子就是创建一个person对象,然后添加三个属性(name,sex,age)和一个方法(getName()),getName()这个方法用于显示对象的名字,这种应该是比较早的一种写法,而现在更推荐这么写:

var person={name:"xiaotangdou",age:"23",sex:"男",getName:function(){alert(this.name),  }};

而这种方式和前面的一种方式是一样的,都有相同的属性和方法。都是创建的时候带有的特征值(charactersic),JavaScript通过这些特征值来定义他们的行为。
1.1属性类型
在JavaScript第五版本的时候只有定义内部才用特征时,描述属性的各种特征实现了JavaScript的引擎,因此JavaScript不能直接的访问他们,为了表示特征内部的值,把规范放在一对方括号中,JavaScript中有两种属性,数据属性和访问属性。
1.1.1:数据属性
数据属性包含数据值的位置,在这个位置可以进行读写操作,数据属性有四个行为特征:(1)[[configuration]]表示是否用delete进行操作。默认为true,(2)[[enumerate]]表示能否用for-in 来循环访问属性,默认值也是true,(3)[[writable]]表示能否修改属性,默认值也是true,(4)[[value]]表示属性的值,默认值是undefined。
1.1.2:访问属性 访问属性不包括数据属性,他们包含一对getter和setter函数(这个函数不是必须得)同样,访问属性也有四个特性,和数据属性前两个一样在添加两个[Get]:在读取属性时调用,默认值也是undefined。[Set]:在写入时调用的属性,默认值也是undefined。
访问属性不能直接定义,必须通过Object.definePerproty()来定义,列如:

var book={name:"JavaScript高级程序设计",edition:5};Object.defineProperty(book,"name",{get:function(){return this.name;}set:function(newName){this.name=newName;this.edition=this.edition}});book.name="java编程思想";alert(book.edition);//5

上面的代码创建一个对象book,定义了两个默认的属性,name和edition.然后创建一个访问属性属性name包含一个get和set。这是一种常用的方式。
2.创建对象的方式
虽然Object构造函数或对象字面量都可以创建耽搁对象,但是这些方式,使用同一个接口创建单个对象,会产生重复的代码,为了解决这个问题,人们开始使用工厂模式产生对象。
2.1.工厂模式
工厂模式是软件工程领域一种广为人知的一种设计模式,这种模式抽象了创建对象的过程。然而对于JavaScript没有办法创建类这个特性,开发人员开创建一个特定的函数,函数内部封装了创建对象的具体细节。例如:

function createPerson(name,age,job){var o=new Object();o.name=name,o.age=age,o.job=job,getName=function(){return this.name;}setName=function(newName){   this.name=newName;  }  return o;}var person1=createPerson("小糖豆",23,"Java开发工程师和Android开发工程师");var person2=createPerson("学霸"21,"李大法官");

函数createPerson()能够接受不同的参数来创建不同的对象。可以无数次调用这个函数,而且每次返回包含三个属性和两个方法的对象,工厂模式虽然解决了对象的相识问题,但是没有解决对象的识别问题,随后JavaScript的发展,出现了新的创建模式。
2.2构造函数模式
JavaScript中构造函数可以创建特定类型的对象,就象Object和array等原生的构造函数,运行时自动会出现在实行环境当中,此外,也可以创建自定义构造函数,从而定义自定义对象类型的属性和方法,例如:用构造函数模式重写上面列子如下:

function Person(name,age,job){this.name=name;this.age=age;this.job=job;this.getName=function(){return this.name;}}var person1=new Person("小糖豆"23,“Java开发工程师”);var person2=new Person("李学霸"21,“李大律师”);

在这个例子中,Person()函数取代了createPerson()函数,值得注意的是:Person()中代码除了与createPerson()中相同部分外,还存在以下不同之处:

  • 没有显示的创建对象;
  • 没有将属性和方法赋值给this对象
  • 没有return语句
    此外,要创建一个对象必须通过new关键字来创建,而且首字母P应该大写。这个习惯其实和其他面向对象程序设计规范来规定的。
    当通过new操作符,其实会经历下面这4个步骤:
    (1):创建一个对象;
    (2):将构造函数的作用域赋值给新对象(因此this就是指的是这个新对象)
    (3):执行构造函数的代码;
    (4):返回对象
    在前面的例子中person1和person2分别保存着Person的一个不同的实例,这两个对象都是有一个constructionor(构造函数)属性,该属性指向Person,如下
alert(person1.construtctor==Person)//truealert(person2.construtctor==Person)//true

对象construtctor属性最初用来是表示对象类型的,但是提到对象检测,还是用instanceof来检测;例如:

alert(person1.instanceof==Person)//truealert(person1.instanceof==Object)//truealert(person2.instanceof==Person)//truealert(person2.instanceof==Object)//true

创建自定义对象意味着是新的一种数据类型,正是因为构造函数模式胜过工厂模式的地方,在上面这个例子中,person1和2都是Object的一个实例,是因为所以的对象都是继承自Object(稍后讨论)。
2.2.1.1构造函数当做函数调用
构造函数和其他函数唯一的区别是调用的方式不一样,不过构造函数毕竟是函数,不存在定义构造函数的特殊语法,那么任何函数只要通过new操作符创建都是可以看做是构造函数,如果不用new操作符调用,那么跟普通函数没有什么两样。例如:

//当做构造函数调用var person=new Person("小糖豆",23,"java开发工程师");person.getName();//小糖豆//当做普通函数调用Person(""小糖豆",23,"java开发工程师"");windows.getName();//小糖豆//在另一个函数作用于中调用var o=new Object();Person.call(o,"小糖豆",23,"java开发工程师");o.getName();//小糖豆

这个例子中前两行代码展示了构造函数的典型用法,即通过new操作符创建对象。
2.2.1.2构造函数模型存在的问题
构造函数虽然好用,但是也不是没有缺点,使用构造函数存在的主要问题:就是每一个方法都要在实例中重新创建一遍,在前面的例子中国person1和person2中的getName(),但是两个方法都在存在不同的Function的实例中,不要忘了JavaScript中函数就是对象。没定义一个函数其实就是创建了一个对象,
从逻辑角度来说现在的构造函数可以定义为:

function Person(name,age,job){this.naem=name;this.age=age;this.job=job;this.getName=new Function("return this.name")}

然而创建两个person对象时,创建两个Function对象时完全没有必要的,况且有this对象在,根本不用再执行代码吧函数绑定到指定对象上面,因此,大家可以这么写:把函数定义转到构造函数外面来解决这个问题。例如:

function Person(name,age,job){this.naem=name;this.age=age;this.job=job;this.getName=getName;}function getName(){return this.name;}

在这个例子中,我们把getName()函数定义转到构造函数外面,而在于构造函数内部,我们把这个getName属性设置为一个等于全局的函数。这样一来,由于getName包含一个指向函数的指针,因此person1和person2共享这个全局的作用域定义中的getName()函数。而这样做确实是解决了两个函数做同一件事的问题,可是新的问题来了:在全局作用与中定义的函数只能通过某个特定的对象调用,这个让全局作用域有点名副其实,而更让人无法接受的是:如果对象需要定义很多方法,那么久的定义很多全局函数,对于我们这个自定义引用类型就没有丝毫的封装性可言了好在这个问题可以通过原型模式来解决

对于原型模式是JavaScript中的一个重要的知识点;我们在下一篇中详细的讨论一下。
Javascript面向对象编程(2)-创建对象重要方法原型模式

5 0
原创粉丝点击