当前位置: 首页 > 科技观察

理解了面向对象之后,突破了本地境界,代码牛逼!

时间:2023-03-20 00:34:33 科技观察

一万人心中有一万个哈姆雷特,一万个开发者心中有一万个面向对象思想的理解。在这里我只简单说明一下我对面向对象思想的理解,希望对大家有所帮助!基本概念在程序中,我们使用对象来构建现实世界的模型,简化并提供难以(或不可能)使用的功能,以供访问。这段解释摘自MDN,上面写着evenIt'satwist。这里我们可以用喂鸭子的方式来理解面向对象,粗略的说,长得像鸭子,那就是鸭子。人和机器的区别在于,人有主观意识,而机器没有。一个尖嘴巴,扁脑袋,会吱吱叫,会游泳的生物,那么这就是我们用对象思维构造的鸭子类。机器不会想象这其实是一只和人类一样具有主观意识的大鹅。对象的组成一个基本的对象是由几种数据类型组成的,如果分成大类的话,可以分为行为属性和属性属性:所有的数据类型都可以认为是对象的属性(小鸭的体重,翅膀,feet等是属性)Behavior:一般指一个函数,赋予对象能力(小鸭会游泳,那么游泳的行为就是小鸭的能力)实例化对象到此为止,我们创建了一只鸭子类,此时鸭子只是一个初始化状态,相当于被冻结了。我们需要对鸭子进行解包,我们可以使用new关键字来实例化鸭子对象。这样我们就得到了一个全新的鸭子对象。new关键字究竟做了什么?可以参考如下代码:varobj={};//获取方法的第一个参数(并删除第一个参数),也就是构造函数varConstructor=[].shift.apply(arguments);//将new对象的内部属性__proto__指向构造函数的原型,这样new对象就可以访问原型中的属性和方法obj.__proto__=Constructor.prototype;//得到构造函数的返回值varret=Constructor.apply(obj,arguments);//如果返回值是对象,则返回对象,否则返回构造函数的实例对象returntypeofret==="object"?回复:对象;intheobject对于这个问题,很多初学者都被这个this指向搞糊涂了。其实理解这个,我们只需要记住一句话谁在调用它,it指向谁,this指向当前调用它的执行环境经典例子:varobj={foo:function(){console.log(this.bar)},bar:1};varfoo=obj.foo;varbar=2;obj.foo()//1foo()//2js中的数据类型分为基本数据类型和参考数据类型。原始数据类型按值访问,引用数据类型按引用访问。对象把所有的引用放在栈上,把所有的值放在堆上。获取一个对象的值,需要先获取对象的引用,然后根据引用找到对应的值。如果引用对应的值是函数,由于函数是单个值,所以可以存在不同的执行上下文。那么问题来了,同一个函数在不同的环境中被调用,我们如何获取函数内部当前的执行环境呢?是的,这个的出现正是为了解决这样的场景。总结:一堆属性和行为聚集在一起形成一个基本对象。可以通过new关键字实例化一个对象。由于执行环境不同,对象内部的this点也不同。在调用对象方法时,需要注意this的指向问题。对象系统我们在上面提到了一个基本对象的组成。但是在我们实际的开发中,远比这复杂。往往是多层对象的嵌套或者多个对象通过一个映射文件相互关联,或者一个对象继承另一个对象……从而构建一个更加庞大的对象世界,解决更加复杂的应用场景。我们称这种复杂的对象为对象系统,这种思想被称为面向对象编程的显式原型概念:每个函数都有一个默认的原型属性,使你能够为对象添加属性和方法。functionpeople(name){this.name=name;this.say=function(){console.log(`你好!我是${name}`);};}people.prototype.kungfu=function(){console.log(`我是${this.name},我会中国功夫`);};constqad=newpeople('秦爱德');constzs=newpeople('张三');console.log(qad);console.log(qad.say());console.log(qad.kungfu());console.log(zs);console.log(zs.say());console.log(zs.kungfu());上面的代码创建了一个people构造函数,在其中添加了一个name属性和say方法,并在其原型中添加了一个kungfu方法。如何理解内部属性和原型属性?这里我们可以使用css样式来简单易懂haha

上面我们创建了一个label和label添加了一个内联样式和一个外部样式,如果构造函数对齐,则内联样式对应内部属性,是后面函数特有的,外部样式对应原型属性,可以是public并且可以在多个地方使用。由于每次new一个构造函数new,都会重新生成内部属性,而原型属性不会,所以这样也避免了内存浪费。并且可以基于原型实现原型继承操作。构造函数概念:每个对象都会有一个默认的构造函数,它指向当前原型对象的构造函数。console.log(qad.__proto__.constructor===people);//true一图胜千言带有属性的构造函数指向这个构造函数的隐式原型(proto)概念:每个对象都有一个_proto_属性,它指向创建该对象的构造函数的原型。console.log(qad.__proto__===people.prototype);//true万物皆对象,函数也是对象。只要是对象,它就具有_proto_属性,所以_proto_是构造函数和原型之间的一个连接,通过从里到外在构造函数中查找原型的属性和方法来建立连接。原型链当我们创建构造函数并访问其中的某个属性时。它会先从构造函数本身开始查找,然后从显式原型(prototype)开始查找,再从隐式原型(__proto__)查找,再从对象的__proto__查找,直到为null。有值就返回对应的值,没有值就返回undefined。我们把这个由内到外的搜索过程称为原型链。一张图片胜过千言万语。善用面向对象的思想。如上所述,我们可以使用对象来构建现实世界的模型,并简化复杂的问题。要用好面向对象的思想,需要牢记面向对象的三大特点和几条原则。三大特色1:浓缩了中华文化的博大精深。,属性,业务逻辑等)packaging:packaging(提供一个容器来存放封装后的代码,打包后,对外输出)packaging中还有一个概念叫抽象,拆分后很好理解(把"like结合“把东西抽出来”的意思是:我们把一堆相似的属性、行为、逻辑抽取出来,存放在一个包装对象中,控制输入输出参数,供别人调用。这就是封装。2:InheritanceInheritance:Continue(继续继续)Inheritance:Undertake(承接重任的延续,发扬光大)组合是:子类继续使用父类的行为或属性,对业务进行合理改造和扩展,并且输出新的对象,有点儿子承父业,青出于蓝的意思3:多态性:多状态:状态和形式的结合意味着同一个实例对象在多个状态下有不同的显示形式。简单理解就是一个函数可以通过不同的输入参数得到不同的输出结果。几个原则1:单一职责原则一个类或者一个函数必须实现单一的功能,不能乱七八糟,越纯粹越好。一旦函数变得不纯,内部就会实现多个函数。当我们在多个地方使用这个功能时,往往会因为不够纯粹而写出很多兼容的代码。2:开放和封闭原则一个类应该保持开放以进行扩展,关闭以进行修改。比如我们封装一个函数,就尽量预留一个空洞,方便以后迭代新的函数,避免直接改之前已经写好的代码。3:里氏代换原则里氏代换原则主要用于约束继承。子类可以扩展父类的功能,但不能改变父类原有的功能。如果子类不能完全实现父类的方法,或者父类的一些方法在子类中已经被“扭曲”了,建议打破父子继承关系,使用依赖、聚合、组合等关系而不是继承。4:依赖倒置原则上层模块不应该依赖下层模块,两者都应该依赖于它的抽象。简而言之,就是面向接口的开发。每个类都提供一个接口或抽象类。抽象类往往比较稳定。当下层细节发生变化时,不应直接影响上层。细节取决于抽象。只要抽象保持不变,程序就不应该改变。5:组合聚合复用原则代码复用时,尽量先使用组合或聚合等关联关系实现,再考虑使用继承关系实现。6:高聚低耦合顾名思义,高度相似的东西应该聚在一起,低相似的东西不要耦合在一起。js本身是一种面向对象的编程语言。在我们日常的开发中,每时每刻都在享受着面向对象带给我们的编程体验。