当前位置: 首页 > Web前端 > JavaScript

面向对象学习笔记

时间:2023-03-27 00:28:44 JavaScript

本文参考《javaScript高级程序设计》第三版,俗称“小红书”。graphTBA[创建对象的方法]A-->B(literal)A-->C(factorymode)A-->D(constructormode)-->E(newObject)A-->F(Prototypemode)样式C填充:#2ff,填充不透明度:0.1,描边:#faa,描边宽度:4px,颜色:bluestyleD填充:#2ff,填充不透明度:0.1,描边:#faa,描边宽度:4px,color:bluestyleFfill:#2ff,fill-opacity:0.1,stroke:#faa,stroke-width:4px,color:blue下面重点对比工厂模式、构造器模式、原型模式。工厂模式定义:工厂模式是软件工程领域的一种设计模式。优点:函数可以多次调用,可以解决创建多个相似对象的问题。缺点:无法解决物体识别问题(无法知道物体的类型)。functionStudent(姓名,年龄,爱好){letp=newObject();//显式创建一个对象p.name=name;p.age=年龄;p.hobby=function(){console.log(`我的爱好是${hobby}`);}returnp;}letstudentA=Student('xiaoMing',10,'drawing')letstudentB=Student('xiaoHua',12,'dance')构造函数模式使用构造函数重写上面的例子:functionStudent(name,年龄,爱好){this.name=name;这个。年龄=年龄;this.hobby=function(){console.log(`我的爱好是${爱好}`);}}letstudentA=newStudent('xiaoMing',10,'drawing');letstudentB=newStudent('xiaoHua',12,'dance');/*******************检测实例类型******************/console.log(studentAinstanceofStudent);//trueconsole.log(studentBinstanceofStudent);//trueconsole.log(studentAinstanceofObject);//trueconsole.log(studentBinstanceofObject);//true/************不同实例同名函数不相等************/console.log(studentA.hobby===studentB。爱好);//false构造函数的函数名首字母始终大写。构造函数本身就是一个函数,一个可以用来创建对象的函数。new运算符经历以下步骤:创建一个对象。将构造函数的范围分配给新对象(因此,this指向新对象)。向新对象添加属性(即:执行构造函数中的代码)。返回新对象。优点:它的实例可以被识别为特定的类型。缺点:每个方法都必须在实例上创建。不同实例上的同名函数不相等。如果构造函数内部的自定义函数定义在构造函数外部的作用域中,那么这些自定义函数的封装性会极差。原型模式定义:每个函数都有一个原型(prototype)属性,它是一个指向特定对象(函数的原型对象)的指针。优点:所有的对象实例都可以共享原型对象的属性和方法。函数Student(){}Student.prototype.name='Jack';学生.prototype.age=12;Student.prototype.hobby=function(){returnthis.name;};letstudentD=newStudent();letstudentE=newStudent();/**************实例共享原型对象的方法**************/console.log(studentD.hobby===studentE.hobby);//真1。理解原型对象的定义:一旦创建了一个函数,就会按照特定的规则为该函数创建一个原型属性,指向该函数的原型对象。所有的原型对象默认只会得到一个构造函数(constructorfunction)属性(指针):这个属性指向原型属性所在的函数;其他方法继承自Object。Constructor构造函数:当调用构造函数创建一个新的实例时,该实例包含一个指针(指向构造函数的原型对象)。ECMA-262第五版将此指针定义为[[prototype]],但浏览器支持__proto__访问。isPrototypeOf()测试一个对象是否存在于另一个对象的原型链中。console.log(Student.prototype.isPrototypeOf(studentE));//trueconsole.log(Student.prototype.isPrototypeOf(studentD));//trueObject.getPrototypeOf()获取对象的原型console.log(Object.getPrototypeOf(studentD));如下图所示:搜索对象属性在访问对象的属性时:首先会在实例对象上搜索指定的属性名,如果找到则返回该属性的值;否则会在实例中查找属性继续在对象的原型对象上查找,找到则返回属性值,找不到则返回undefined。实例属性与原型对象属性的联系为实例对象添加属性时,新添加的属性会屏蔽原型对象中的同名属性,此时,原型对象中的同名属性无法在实例对象中访问。在实例对象中为这个新属性设置任何值都不会影响原型对象中具有相同名称的属性。如果使用delete删除实例对象中的某个属性,则可以在原型对象中重新访问同名属性。hasOwnProperty()检查实例对象中是否存在属性。下面的代码说明了functionStudent(){}Student.prototype.name='Jack';Student.prototype.age=12;Student.prototype.hobby=function(){returnthis.name;};letstudentSth=newStudent();//创建一个实例studentSth.grade=90;//给实例对象添加一个属性grade/***实例studentSth对象中有一个属性grade***/console.log(studentSth.hasOwnProperty('grade'));//true/*属性名称在实例studentSth对象中不存在*/console.log(studentSth.hasOwnProperty('name'));//错误2。原型对象和inoperatorfor(letattributeinstudentSth){console.log(attribute);}/**依次打印出实例对象和实例原型对象中的属性名**///成绩//名字//age//hobbyObeject.keys()/****在实例上调用****/console.log(Object.keys(studentSth));//["grade"]/****调用实例的原型对象****/console.log(Object.keys(studentSth.__proto__));//["name","age","hobby"]Object.getOwnPropertyNames()/***在实例上调用****/console.log(Object.getOwnPropertyNames(studentSth));//["grade"]/****调用实例的原型对象****/console.log(Object.getOwnPropertyNames(studenttSth.__proto__));//["constructor","name","age","hobby"]//constructor是一个不可枚举的属性3.原型的动态性可以随时给原型对象添加属性和方法,并且,修改可以立即反映在所有实例对象中4.原生对象的原型通过原生对象的原型,可以获得默认方法的引用,也可以自定义一个新的方法。String.prototype.say=function(){console.log('修改了原生对象的原型属性');}letstr='thisisa';str.say()//修改了原生对象的原型属性对象5。原型对象的问题问题1:省略为构造函数传递初始化参数。问题2:属性共享的性质。6.构造器模式与原型模式的结合