收藏 分享(赏)

JS对象与原型.docx

上传人:fmgc7290 文档编号:7219364 上传时间:2019-05-10 格式:DOCX 页数:13 大小:2.84MB
下载 相关 举报
JS对象与原型.docx_第1页
第1页 / 共13页
JS对象与原型.docx_第2页
第2页 / 共13页
JS对象与原型.docx_第3页
第3页 / 共13页
JS对象与原型.docx_第4页
第4页 / 共13页
JS对象与原型.docx_第5页
第5页 / 共13页
点击查看更多>>
资源描述

1、面向对象设计引用类型(function string number array date) -Object-对象原型-函数表达式-数据类型面向对象:类和对象,通过类可以创建任意多个具有相同属性和方法的对象。ECMA 定义对象:无序属性的集合,其属性可以包含基本值、对象或者函数。相当于一组没有特定顺序的值,对象的每个属性或方法都有一个名字,而每个名字映射到一个值。即:对象就是一组键值对,其中值可以是数据或函数。每个对象都是基于一个引用类型创建的。Object 是所有 JS 对象的基类prototype 是对象的原型obj.constructor 是创造该对象的构造器一、创建自定义对象var pe

2、rson = new Object();person.name=“dujie“;person.say = function()alert(this.name);字面量法:var person = name:“dujie“,say:function()alert(this.name);二、对象属性内部采用的特性,描述了属性的各种特征,这些特性是为了实现 JavaScript 引擎用的,在 js 中不能直接访问,为了表示特性是内部值,规范把他们放在了两对方括号里 例如:EnumerableECMAScript 中有两种属性:数据属性和访问器属性1.数据属性:包含一个数据值的位置,行为 (在这个位置

3、可以读取和写入值)4 个描述行为:1.Configurable:表示能否通过 delete 删除属性从而重新定义属性,能否修改属性的特性或者能否把属性修改为访问器属性。默认值为 true2.Enumerable:表示能否通过 for-in 循环返回属性,默认为 true3.Writable:表示能否修改属性的值 默认为 true4.Value:包含这个属性的数据值。默认为 undefined,从这个位置读取或写入保存属性的值定义对象时 var person=name:“dujie“ Value特性将被设置为“dujie“若要修改属性默认的特性,必须使用 ECMAScript5 的 Object

4、.defineProperty()方法Object.defineProperty(obj,“属性名“,描述符对象)描述符对象的属性必须是 configurable enumerable writable value 例如:var person = ;Object.defineProperty(person,“name“,writable:false, 属性值不可以修改,变成只读configurable:false 不可从对象中删除属性 delete person.name 无效果value:“dujie“);alert(person.name) /dujieperson.name=“jack“

5、;alert(person.name) /dujie注意:可以多次调用 Object.defineProperty()方法修改同一属性的特性,但是把 configurable 特性设置为false 后就会有限制,除 writable 之外的特性都会报错原型对象模仿类,实例化对象实例化对象流程:1.创建 obj = new Object()2.将 obj 的内部_proto_指向构造函数 A 的 prototype 属性,同时 obj.constructor = A.prototype.constructor 类的实例对象的 constructor 属性永远指向构造函数的 prototype.c

6、onstructor,构造函数 person原型对象 person.prototype对象实例 person1三者的关系:每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个指向原型对象的内部指针。原型链:原型对象等于另一个类型的实例,将包含一个指向另一个原型的指针,相应地另一个原型中也包含指向另一个构造函数的指针,层层递进,构成了原型连在实例中无法访问 prototype 属性,可通过 isPrototypeOf()方法来确定对象之间是否存在这种关系person.prototype.isPrototypeOf(person1) /返回 true 因为 pers

7、on1 内部有一个指向 person.prototype 的指针,所以返回 true如果实例中的 prototype 指向调用 isPrototypeOf()方法的对象(person.prototype),就返回 trueECMAScript 5 增加方法:Object.getPrototypeOf() 返回Prototype的值( 对象原型)(IE9+ Firefox3.5 Safari5+ Opera12+ Chrome 支持此方法)alert(Object.getPrototypeOf(person1)=person.prototype); /true alert(Object.getP

8、rototypeOf(person1).name);原型模式执行流程:读取实例属性值:1.先从对象实例开始搜索,有则返回该属性的值,没有继续根据链接搜索原型对象,最后返回原型中的属性值2.不能通过对象实例重写原型中的值,如果在实例中添加了一个与原型中具有相同名字的属性,那么就在实例中创建该属性,该属性会屏蔽原型中的属性(但不会修改原型中的属性值)解除屏蔽:即使在实例中把属性设置为 null 也只会在实例中设置这个属性,而不会恢复其指向原型的链接,可以使用 delete 操作符完全删除这个实例属性,让我们重新访问原型中的属性。function person()person.prototype.n

9、ame=dujie,person.prototype.age=25,person.prototype.say=function()console.log(this.name);var person1 =new person();var person2 =new person();person1.name=lili;console.log(person1.name); /liliconsole.log(person2.name); /dujiedelete person1.name;console.log(person1.name); / dujieconsole.log(person2.nam

10、e); /dujiehasOwnProperty()方法:检测一个属性存在于实例中还是在原型中(这个方法只在属性存在于对象实例中时才返回 true)person1.hasOwnproperty(“name“); /实例中有返回 true 无返回 false通过此方法,判断访问的是实例属性还是原型属性就一清二楚了Object.getOwnPropertyDescriptor(person1,name) 只运用于实例属性,要取得原型对象属性描述符,必须直接在原型对象上调用 Object.getOwnPropertyDescriptor( )方法原型于 in 操作符in 操作符在单独使用时,会在通过

11、对象能够访问给定属性时返回 true 无论属性存在于实例中还是原型中person1.hasOwnProtoperty(“name“); /返回 false 在原型中alert(“name“ in person1) / 返回 true可同时使用 hasOwnProperty()方法和 in 操作符,确定该属性是在原型中还是在实例中function hasPrototypeProperty(object,name)return !object.hasOwnProperty(name)确定属性是在原型中的属性for (i in obj):返回所有能够通过对象访问的,可枚举的属性,其中既包括存在于实例

12、中的属性,也包括存在于原型中的属性。.取得对象中所有可枚举的实例属性,可使用 Object.keys()方法,接受一个对象作为参数,返回一个包含所有可枚举的属性的字符串数组实例的话,只返回实例中的属性原型:只返回原型中的属性Object.getOwnPropertyNames(obj) 获得所有实例属性,无论是否可枚举实例的话,只返回实例中的属性原型:只返回原型中的属性为什么会指向 Object?Box.prototype=相当于新创建了一个对象,而每创建一个函数,就会同时创建它的 prototype,这个对象也会自动获取 constructor 属性,所以新对象的 constructor 重

13、写了 Box 原来的 constructor,因此指向新对象,新对象没有构造函数,就是默认的 Object解决:原型语法简化:function Person()Person.prototype=constructor: Person /确保该属性指向构造函数name:dujie,age:25,say:function();目的:简化 person.protorype 的重复写弊端:constructor 属性不在指向 person 了此种写法:相当于重写( 重新定义了一个对象) 了 prototype 对象,因此 constructor 属性也就变成了新的对象的 constructor 属性(

14、指向 Object 构造函数) ,不再指向 person 函数,因此通过 constructor 已经无法确定对象的类型了如上: person1.constructor = person /falseperson1.constructor = Object /ture可以在重写对象时加上 constructor:Person ,但是重写会导致他的 Enumerable特性设置为 true,默认情况下原生的 constructor 属性是不可枚举的,如想兼容 ECMAScript5 可以通过 Object.defineProperty()设置Object.defineProperty(Perso

15、n.prototype,“constructor“,enumerable:false,value:Person)原型的声明是有先后顺序的,所以重写的原型会切断之前的原型。原型的动态性:实例中的指针仅指向原型,而不指向构造函数function Person()var friend=new Person(); /创建 person 实例,指向 person 原型Person.prototype = /重写了原型对象constructor:Person,name:dujie,age:25var per=new Person();console.log(friend.name); /undefined

16、 /调用属性时发生错误,因为 friend 指向的原型中不包含该属性console.log(per.name); /dujie /重写原型后实例化,具有该属性返回重写原型对象截断了现有原型于任何之前已经存在的对象实例之间的联系,他们引用的任然是最初的原型。原型对象不仅仅可以再自定义的对象的情况下使用,而 ECMAScript 内置对象的引用类型都可以使用这种方式,并且引用类型本身也使用了原型。原生引用类型都是这么创建的(Object Array String 等)都在其构造函数的原型上定义了方法Array.prototype.sortString.prototype.substring可以取得

17、默认的方法,也可以定义新的方法组合使用构造函数于原型模式构造函数:定义实例属性原型模式:定义方法和共享属性function Person(name,age,job)this.name=name;this.age=age;this.job=job;this.friend=lili,liing;Person.prototype = constructor:Person,sayName:function()console.log(this.name);var person1=new Person(dujie,25,programe);var person2=new Person(limeng,25,

18、doctor);person1.friend.push(van);console.log(person1.friend);console.log(person2.friend);console.log(person1.friend=person2.friend);console.log(person1.sayName=person2.sayName);“lili“, “liing“, “van“lili“, “liing“falsetrue原型模式:不管你是否调用了原型中的共享方法,它都会初始化原型中的方法,并且声明一个对象时,构造函数+原型 的模式分开写不方便维护,最好把构造函数和原型封装到

19、一起,为了解决这个问题,可使用动态原型模式动态原型模式:把所有信息都封装在构造函数中,通过在构造函数中初始化原型,又保持了同时使用构造函数与原型的优点(通过检查某个应该存在的方法是否有效,来决定是否需要初始化原型)function Person(name,age,job)this.name=name;this.age=age;this.job=job;if(typeof this.sayName !=“function“) /仅在第一次调用时初始化Person.prototype.sayName = function()var friend = new Person(dujie,25,“Sof

20、tware Engineer“);friend.sayName();第一次调用构造函数时,sayName()方法不存在,然后初始化原型,第二次调用时,就不会初始化,并且第二次创建新对象,原型也不再初始化了。注意:使用动态原型模式,不可以再使用字面量的方式重写原型,因为会切断实例和原型之间的联系。二、原型连实现继承基本思想:利用原型让一个引用类型继承另一个引用类型的属性和方法构造函数 原型 实例之间的关系:每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个指向原型对象的内部指针让原型对象等于另一个类型的实例:此时原型对象将包含另一个指向另一个原型的指针,相应地,

21、另一个原型中也包含着一个指向另一个构造函数的指针。假如另一个原型又是另一个类型的实例,上述关系依然成立,层层递进,就构成了实例于原型的链条,成为原型链。function SuperType()this.name=dujie;SuperType.prototype.getSuperValue =function()return this.name;function SubType()this.age =100;SubType.prototype = new SuperType(); /子类原型继承了父类实例SubType.prototype.getSubValue= function()retu

22、rn this.age;var instance =new SubType();alert(instance.getSuperValue(); dujie /调用父类中的方法继承通过:创建超类实例,并将该实例赋值给子类的原型来实现,实现的本质是重写原型对象,代之以一个新类型的实例。原来存在于超类实例中的所有属性和方法,现在也存在于子类的原型中了,确立继承关系后,我们给子类原型添加了一个新的方法,这样在继承了超类的属性和方法的基础上又添加了一个新的方法。3.方法定义2.在通过原型链实现继承时,不能使用对象字面量创建原型方法,这样做会重写原型链。原型链的问题:1. 包含引用类型值得原型,引用类型的原有属性值会被所有实例共享2. 在创建原型链的时候不能向超类中传参解决原型值带来的问题:组合式继承:将原型链和借用构造函数的技术组合到一起思路:使用原型链实现对原型属性和方法的继承。而通过借用构造函数来实现对实例属性的继承。通过在原型上定义方法实现了函数复用,又能保证每个实例都有它自己的属性。

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 企业管理 > 管理学资料

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报