一、JavaScript面向对象前言1.1什么是对象?Everythingisobject(一切皆对象)。究竟什么是对象,我们可以从两个层面来理解。对象是单个事物的抽象。一本书、一辆车和一个人都可以是对象,数据库、网页和与远程服务器的连接也是如此。当对象被抽象为对象时,对象之间的关系就变成了对象之间的关系,这样就可以模拟真实情况,从而可以对对象进行编程。对象是封装了属性(property)和方法(method)的容器。属性是对象的状态,方法是对象的行为(完成某项任务)。例如,我们可以将动物抽象为动物对象,用“属性”来记录具体的动物,用“方法”来表示动物的某些行为(奔跑、狩猎、休息等)。在实际开发中,一个对象就是一个一个抽象的概念,可以简单理解为:数据集或函数集。1.2什么是面向对象?面向对象只是对过程代码的高度封装,目的是为了提高代码的开发效率和可维护性小编的理解:面向对象就是在使用一个对象的时候,可以直接使用它提供的功能和忽略其他功能。内部组成。面向对象不一定只存在于编程世界,它在我们的生活中无处不在;比如你可以用遥控器操作家里的电视机,但其实你并不了解电视机,只要知道里面有哪些零件,我就可以用遥控器操作电视机。这是一种面向对象的思想。1.2.1什么是面向对象编程?Object-OrientedProgramming——面向对象编程,简称OOP,是一种编程开发思想。它将现实世界中的各种复杂关系抽象为个体对象,然后通过对象之间的分工合作完成对现实世界的模拟。在面向对象的程序开发思想中,每个对象都是一个分工明确的功能中心,可以完成接收信息、处理数据、发送信息等任务。因此,面向对象编程具有灵活性、代码可重用性、模块化程度高等特点,易于维护和开发。与传统的由一系列函数或指令组成的过程式编程(proceduralprogramming)相比,它更适合多人协作。大型软件项目。1.2.2面向对象和面向过程面向过程就是凡事亲力亲为,每一个细节,每一个细节,循序渐进,有条不紊。面向对象就是找到一个对象并指向结果。面向对象把执行者变成指挥官。面向对象不是面向过程。而是面向过程的封装2.对象定义的两种方式2.1字面量定义方式varobj={name:"Tom",sex:"man",age:19,run:function(){console.log("每天跑一公里");}}2.2使用newObject()定义varobj=newObject();obj.name="汤姆";obj.sex="男人";obj.age=19;obj.run=function(){console.log("每天跑一公里");}3.类和对象3.1什么是类?具有相同特征(数据元素)和行为(功能)的对象的抽象是一个类。因此,对象的抽象就是类,类的具体化就是对象。也可以说类的实例就是对象,类其实就是一种数据类型。类有属性,是对象状态的抽象,用数据结构来描述类的属性。一个类有一个操作,它是对象行为的抽象,由操作的名称和实现该操作的方法来描述。3.2类和对象的区别作为初学者,很容易混淆类和对象的概念。类(Class)是一个抽象概念,对象是类的具体实例。例如:人是一个类,司马迁、李白、杜甫都是对象;capital是一个类,北京、伦敦、华盛顿、莫斯科都是对象;动物猫是一个类,Kitty、Grafield、哆啦A梦都是对象。我们可以说Kitty猫重1.5kg,但不能说猫重1.5kg;我们可以说李白是诗人,但不能说人是诗人。状态描述的是具体的对象而不是类,行为是由具体的对象而不是类发出的。3.3类与对象的关系类与对象的关系就像模具与铸件的关系。类实例化的结果是对象,对象的抽象就是类。类描述了一组具有相同特征(属性)和相同行为的对象。classperson{}//这是类$obj=newperson();//类的实例化就是对象4.创建对象的三种方式4.1工厂模式,使用简单的函数创建对象,添加属性和方法对象,然后返回对象//类模板functionPerson(name,sex,age){varobj={};obj.name=名称;obj.sex=性别;obj.age=年龄;obj.run=function(){console.log("每天坚持跑");}返回对象;}//实例化varperson1=Person("Tom","sex",19);//运行person1.run();//输出结果:每天保持运行4.1.1工厂模式的优缺点优点:1、在工厂模式中,用户只需要知道具体要生产的东西,不需要关心具体是什么东西创建过程,甚至是特定产品类别的类名。2、在系统中添加新产品时,我们只需要添加具体的产品类别和对应的实现工厂即可,无需对原有工厂进行任何修改,非常符合“开闭原则”。缺点:1、每增加一个产品,都需要增加一个具体的类和对象实现工厂,使系统中类的数量成倍增加,一定程度上增加了系统的复杂度,同时也增加了系统的专用性系统。类依赖。这不是一件好事。4.2构造函数模式。要创建自定义引用类型,您可以像创建内置对象实例一样使用new运算符。这种方法的缺点是构造函数的每个成员不能重复使用,每个创建的对象只有私有变量和私有方法。Shared//构造函数无法实现(这里创建了一个Class模板)functionPerson(name,sex,age){this.name=name;this.sex=性别;这个。年龄=年龄;this.run=function(){console.log("每天保持运行");}}//实例化(newObject())varperson1=newPerson("Tom","man",19);//Operationperson1.run();//每天保持运行4.2.1构造函数改进//构造全局对象varaction={run:function(){console.log("每天保持运行");}}//构造函数(姓名,性别,年龄){this.name=name;this.sex=性别;这个。年龄=年龄;this.run=action.run;}//实例化varperson1=newPerson("Tom","man",19);person1.run();分析:为什么要改进构造函数?我们都知道,当一个对象被实例化时,那么这个对象就拥有了模板的属性和方法。我们在使用方法的时候,会先在内存中开辟一块空间,然后进行相应的操作。假设我们实例化10000个对象,那么这10000个对象在执行方法时必须在内存中开辟空间,这样只会浪费内存空间。一个操作代替10000个操作不就可以了吗?漂亮,所以小编这里用了一个全局对象。即使有10000个对象,使用这种方法也只会在内存中开辟一个空间。但这也有缺点。我们都知道全局变量和局部变量。全局变量容易造成污染,声明周期长。全局对象也是如此。有没有办法不使用所有对象?当然见下面的第三种创建模式4.3Prototype模式,使用构造函数的prototype属性指定共享属性和方法,即使用构造函数定义实例属性,使用prototype定义共享属性和方法//constructor功能人(姓名,性别,年龄){this.name=name;this.sex=性别;这个。年龄=年龄;}//使用原型对象Object.prototypePerson.prototype.run=function(){console.log("每天坚持跑步");}//实例化varperson1=newPerson("Tom","man",19);person1.run();//每天保持运行5.构造函数、原型对象、实例化三个对象的关系先了解几个属性:__proto__:对象的原型。所有对象(包括函数)都有原型:函数的原型对象。只有函数(准确的说是构造函数)才有constructor:对象上的一个属性,默认指向这个原型的构造函数。6.吃透js中this的方向。无法确定函数何时执行。只有在函数执行的时候才能判断this指向了谁。其实this最终指向的是调用它的对象(这句话有一些问题,后面会解释为什么有问题。虽然网上很多文章都是这么说的,虽然很多情况下不会造成什么问题那样理解,但实际上那样理解是不准确的,所以当你这样理解的时候,会有一种说不清道不明的感觉),那我就深入讨论一下这个问题。eg1:functionshow(){varuser="Tom";console.log(this.user);//undefinedconsole.log(this);//window}show();根据我们上面所说,this最终指向的是调用它的对象。这里的函数show()实际上是被Window对象调用的,下面的代码可以证明。functionshow(){varuser="Tom";console.log(this.user);//undefinedconsole.log(this);//window}window.show();结果和上面的代码一样,所以这次是window调用的eg2:varshow={user:"Tom",fn:function(){console.log(this.user);//Tom}}显示.fn();这里this指向的是对象show,因为你是通过show.fn()调用这个fn的,那么自然指向的就是对象show,这里再说一遍,this的指向在函数创建的时候不能确定,只能在创建的时候确定它被称为,谁调用它就指向谁,你必须弄清楚这一点。要完全理解this的方向,请看下面的例子eg3:varshow={user:"Tom",fn:function(){console.log(this.user);//Tom}}window.show.fn(); 这段代码和上面的代码差不多,但是为什么这里的this没有指向window呢?如果按照上面的理论,thisfinally指向调用它的对象。我先说吧。外语,window在js中是全局对象,我们创建的变量其实就是给window添加属性,所以这里可以使用window指向show对象。先不解释为什么上面这段代码this没有指向window,我们来看一段代码varshow={a:20,b:{a:22,fn:function(){console.log(this.a);//22}}}show.b.fn(); 这里也被objectshow指出了,还this不执行,那你肯定会说我一开始说的不全是错的?其实不是,只是我一开始说的不准确。接下来,我再补充一句。相信你能完全理解这里所指的问题。 情况一:如果一个函数中有this,但是没有被上层对象调用,那么this指向window。这里需要说明的是,在js的严格版中,this并没有指向window,但是我们这里不讨论严格版的问题,想知道的可以自行上网搜索. 情况2:如果一个函数中有this,并且这个函数被上层对象调用,那么this指向上层对象。 情况三:如果函数中有this,函数中包含多个对象,即使这个函数被最外层对象调用,this也只指向其上层对象,例子3可以证明,如果你不不信,那我们继续看几个例子。varshow={a:20,b:{fn:function(){console.log(this.a);//undefined}}}show.b.fn();对象b中虽然没有属性a,但是这个this也指向了对象b,因为this只会指向它的上层对象,而不管这个对象中有没有this想要的东西。还有一个特例,eg4:varshow={a:20,b:{a:22,fn:function(){console.log(this.a);//undefinedconsole.log(this);//窗口}}}vard=show.b.fn;d();这里this指向window,是不是有点迷糊了?其实是你一句话没看懂,这也很关键。 this总是指向最后调用它的对象,也就是说,它取决于执行时调用它的人。例4中,函数fn虽然被对象b引用了,但是在将fn赋值给变量d时,并没有执行,所以最终指向了window,这与例3不同。例3中,fn是直接执行的。这其实大体上是同一个东西,只是在不同的情况下指向不同的东西。上面的总结每个地方都有一些小错误,不能说是错误,但是不同环境情况不同。会有差异,不能一下子讲清楚,只能慢慢体会。this的构造函数版本:functionFn(){this.user="Tom";}vara=newFn();console.log(a.user);//Tom这里objecta可以被点击出functionFnTheuser是因为new关键字可以改变this的方向,把this指向objecta。为什么我说a是一个对象,因为使用new关键字就是创建一个对象实例。要理解这句话,想想我们的例子3,这里我们使用变量a创建了一个Fn的实例(相当于复制了一份Fn到对象a中),此时只是创建,并没有执行,并且函数Fn被对象a调用了,那么this指向自然是对象a,那为什么对象a里面有user呢,因为你把Fn函数拷贝了一份给对象a,使用new关键字就是相当于复制一份。当点击返回时:functionFn(){this.user="Tom";返回{};}vara=newFn();console.log(a.user);//undefinedContinue:functionFn(){this.user="Tom";返回函数(){};}vara=newFn();console.log(a.user);//undefinedgoon:functionFn(){this.user="Tom";返回1;}vara=newFn();console.log(a.user);//Tom继续:functionFn(){this.user="Tom";返回未定义;}vara=newFn();console.log(a.user);//Tom如果返回值是对象,那么this指向返回的对象,如果返回值不是对象,那么this仍然指向函数functionFn(){this.user="汤姆";返回空值;}vara=newFn();console.log(a.user);//Tom虽然null也是一个对象,但是这里this还是指向那个函数的实例,因为null是特殊的7.综上所述,这就是我今天学习的全部内容。希望对学习前端的朋友有所帮助。有问题请留言,我们共同进步!
